summaryrefslogblamecommitdiffstats
path: root/src/core/hle/service/am/library_applet_self_accessor.cpp
blob: c36f141f49b36dbb3109aa936cf97c380b1d6f89 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11





                                                               




                                                                        

















































                                                                                                           

                                                                    

                                
                           

                                
                               

                          
                                    

                                     
                              











































                                                                               

                                              




                                                

                                                                           








                                                                                    
                           







                                                                                                
                                       









                                                                                      
                           






                                                                                                
                                       











































                                                                                        


                                                             
                             
                                              











                                                                     




                                                                                         



                                                           
                                                   











                                                         


                                                                          

                             

                                                                       



















                                                                                                      




                                                                                      



                                                           
                                                                
                     

                                                                         
















                                                                                 

                                                  





                                                                               

                                                                        










                                                                             




                                                                                         





                                                           

                                                   




                                     
                                                                               




                               

                                                               









                                                                         
                                                







                                                                                       
                                                  








                                                                       
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core_timing.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/am_results.h"
#include "core/hle/service/am/frontend/applet_cabinet.h"
#include "core/hle/service/am/frontend/applet_controller.h"
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
#include "core/hle/service/am/frontend/applets.h"
#include "core/hle/service/am/library_applet_self_accessor.h"
#include "core/hle/service/am/storage.h"
#include "core/hle/service/ipc_helpers.h"
#include "hid_core/hid_types.h"

namespace Service::AM {

ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
    : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
        {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
        {2, nullptr, "PopInteractiveInData"},
        {3, nullptr, "PushInteractiveOutData"},
        {5, nullptr, "GetPopInDataEvent"},
        {6, nullptr, "GetPopInteractiveInDataEvent"},
        {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
        {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
        {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
        {13, nullptr, "CanUseApplicationCore"},
        {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
        {15, nullptr, "GetMainAppletApplicationControlProperty"},
        {16, nullptr, "GetMainAppletStorageId"},
        {17, nullptr, "GetCallerAppletIdentityInfoStack"},
        {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
        {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
        {20, nullptr, "PopExtraStorage"},
        {25, nullptr, "GetPopExtraStorageEvent"},
        {30, nullptr, "UnpopInData"},
        {31, nullptr, "UnpopExtraStorage"},
        {40, nullptr, "GetIndirectLayerProducerHandle"},
        {50, nullptr, "ReportVisibleError"},
        {51, nullptr, "ReportVisibleErrorWithErrorContext"},
        {60, nullptr, "GetMainAppletApplicationDesiredLanguage"},
        {70, nullptr, "GetCurrentApplicationId"},
        {80, nullptr, "RequestExitToSelf"},
        {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
        {100, nullptr, "CreateGameMovieTrimmer"},
        {101, nullptr, "ReserveResourceForMovieOperation"},
        {102, nullptr, "UnreserveResourceForMovieOperation"},
        {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
        {120, nullptr, "GetLaunchStorageInfoForDebug"},
        {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
        {140, nullptr, "SetApplicationMemoryReservation"},
        {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
    };
    // clang-format on
    RegisterHandlers(functions);

    switch (system.GetFrontendAppletHolder().GetCurrentAppletId()) {
    case AppletId::Cabinet:
        PushInShowCabinetData();
        break;
    case AppletId::MiiEdit:
        PushInShowMiiEditData();
        break;
    case AppletId::PhotoViewer:
        PushInShowAlbum();
        break;
    case AppletId::SoftwareKeyboard:
        PushInShowSoftwareKeyboard();
        break;
    case AppletId::Controller:
        PushInShowController();
        break;
    default:
        break;
    }
}

ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;

void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
    LOG_INFO(Service_AM, "called");

    if (queue_data.empty()) {
        IPC::ResponseBuilder rb{ctx, 2};
        rb.Push(AM::ResultNoDataInChannel);
        return;
    }

    auto data = queue_data.front();
    queue_data.pop_front();

    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
    rb.Push(ResultSuccess);
    rb.PushIpcInterface<IStorage>(system, std::move(data));
}

void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
    LOG_WARNING(Service_AM, "(STUBBED) called");

    IPC::ResponseBuilder rb{ctx, 2};
    rb.Push(ResultSuccess);
}

void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
    LOG_WARNING(Service_AM, "(STUBBED) called");

    system.Exit();

    IPC::ResponseBuilder rb{ctx, 2};
    rb.Push(ResultSuccess);
}

void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
    struct LibraryAppletInfo {
        AppletId applet_id;
        LibraryAppletMode library_applet_mode;
    };

    LOG_WARNING(Service_AM, "(STUBBED) called");

    const LibraryAppletInfo applet_info{
        .applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId(),
        .library_applet_mode = LibraryAppletMode::AllForeground,
    };

    IPC::ResponseBuilder rb{ctx, 4};
    rb.Push(ResultSuccess);
    rb.PushRaw(applet_info);
}

void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
    struct AppletIdentityInfo {
        AppletId applet_id;
        INSERT_PADDING_BYTES(0x4);
        u64 application_id;
    };
    static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");

    LOG_WARNING(Service_AM, "(STUBBED) called");

    const AppletIdentityInfo applet_info{
        .applet_id = AppletId::QLaunch,
        .application_id = 0x0100000000001000ull,
    };

    IPC::ResponseBuilder rb{ctx, 6};
    rb.Push(ResultSuccess);
    rb.PushRaw(applet_info);
}

void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
    struct AppletIdentityInfo {
        AppletId applet_id;
        INSERT_PADDING_BYTES(0x4);
        u64 application_id;
    };
    static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
    LOG_WARNING(Service_AM, "(STUBBED) called");

    const AppletIdentityInfo applet_info{
        .applet_id = AppletId::QLaunch,
        .application_id = 0x0100000000001000ull,
    };

    IPC::ResponseBuilder rb{ctx, 6};
    rb.Push(ResultSuccess);
    rb.PushRaw(applet_info);
}

void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
    LOG_WARNING(Service_AM, "(STUBBED) called");

    IPC::ResponseBuilder rb{ctx, 3};
    rb.Push(ResultSuccess);
    rb.Push<u32>(0);
}

void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
    const Service::Account::ProfileManager manager{};
    bool is_empty{true};
    s32 user_count{-1};

    LOG_INFO(Service_AM, "called");

    if (manager.GetUserCount() > 0) {
        is_empty = false;
        user_count = static_cast<s32>(manager.GetUserCount());
        ctx.WriteBuffer(manager.GetAllUsers());
    }

    IPC::ResponseBuilder rb{ctx, 4};
    rb.Push(ResultSuccess);
    rb.Push<u8>(is_empty);
    rb.Push(user_count);
}

void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
    LOG_WARNING(Service_AM, "(STUBBED) called");

    IPC::ResponseBuilder rb{ctx, 3};
    rb.Push(ResultSuccess);
    rb.Push<u8>(0);
}

void ILibraryAppletSelfAccessor::PushInShowAlbum() {
    const CommonArguments arguments{
        .arguments_version = CommonArgumentVersion::Version3,
        .size = CommonArgumentSize::Version3,
        .library_version = 1,
        .theme_color = ThemeColor::BasicBlack,
        .play_startup_sound = true,
        .system_tick = system.CoreTiming().GetClockTicks(),
    };

    std::vector<u8> argument_data(sizeof(arguments));
    std::vector<u8> settings_data{2};
    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
    queue_data.emplace_back(std::move(argument_data));
    queue_data.emplace_back(std::move(settings_data));
}

void ILibraryAppletSelfAccessor::PushInShowController() {
    const CommonArguments common_args = {
        .arguments_version = CommonArgumentVersion::Version3,
        .size = CommonArgumentSize::Version3,
        .library_version = static_cast<u32>(Frontend::ControllerAppletVersion::Version8),
        .theme_color = ThemeColor::BasicBlack,
        .play_startup_sound = true,
        .system_tick = system.CoreTiming().GetClockTicks(),
    };

    Frontend::ControllerSupportArgNew user_args = {
        .header = {.player_count_min = 1,
                   .player_count_max = 4,
                   .enable_take_over_connection = true,
                   .enable_left_justify = false,
                   .enable_permit_joy_dual = true,
                   .enable_single_mode = false,
                   .enable_identification_color = false},
        .identification_colors = {},
        .enable_explain_text = false,
        .explain_text = {},
    };

    Frontend::ControllerSupportArgPrivate private_args = {
        .arg_private_size = sizeof(Frontend::ControllerSupportArgPrivate),
        .arg_size = sizeof(Frontend::ControllerSupportArgNew),
        .is_home_menu = true,
        .flag_1 = true,
        .mode = Frontend::ControllerSupportMode::ShowControllerSupport,
        .caller = Frontend::ControllerSupportCaller::
            Application, // switchbrew: Always zero except with
                         // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
                         // which sets this to the input param
        .style_set = Core::HID::NpadStyleSet::None,
        .joy_hold_type = 0,
    };
    std::vector<u8> common_args_data(sizeof(common_args));
    std::vector<u8> private_args_data(sizeof(private_args));
    std::vector<u8> user_args_data(sizeof(user_args));

    std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
    std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
    std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));

    queue_data.emplace_back(std::move(common_args_data));
    queue_data.emplace_back(std::move(private_args_data));
    queue_data.emplace_back(std::move(user_args_data));
}

void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
    const CommonArguments arguments{
        .arguments_version = CommonArgumentVersion::Version3,
        .size = CommonArgumentSize::Version3,
        .library_version = static_cast<u32>(Frontend::CabinetAppletVersion::Version1),
        .theme_color = ThemeColor::BasicBlack,
        .play_startup_sound = true,
        .system_tick = system.CoreTiming().GetClockTicks(),
    };

    const Frontend::StartParamForAmiiboSettings amiibo_settings{
        .param_1 = 0,
        .applet_mode = system.GetFrontendAppletHolder().GetCabinetMode(),
        .flags = Frontend::CabinetFlags::None,
        .amiibo_settings_1 = 0,
        .device_handle = 0,
        .tag_info{},
        .register_info{},
        .amiibo_settings_3{},
    };

    std::vector<u8> argument_data(sizeof(arguments));
    std::vector<u8> settings_data(sizeof(amiibo_settings));
    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
    std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
    queue_data.emplace_back(std::move(argument_data));
    queue_data.emplace_back(std::move(settings_data));
}

void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
    struct MiiEditV3 {
        Frontend::MiiEditAppletInputCommon common;
        Frontend::MiiEditAppletInputV3 input;
    };
    static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");

    MiiEditV3 mii_arguments{
        .common =
            {
                .version = Frontend::MiiEditAppletVersion::Version3,
                .applet_mode = Frontend::MiiEditAppletMode::ShowMiiEdit,
            },
        .input{},
    };

    std::vector<u8> argument_data(sizeof(mii_arguments));
    std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));

    queue_data.emplace_back(std::move(argument_data));
}

void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
    const CommonArguments arguments{
        .arguments_version = CommonArgumentVersion::Version3,
        .size = CommonArgumentSize::Version3,
        .library_version = static_cast<u32>(Frontend::SwkbdAppletVersion::Version524301),
        .theme_color = ThemeColor::BasicBlack,
        .play_startup_sound = true,
        .system_tick = system.CoreTiming().GetClockTicks(),
    };

    std::vector<char16_t> initial_string(0);

    const Frontend::SwkbdConfigCommon swkbd_config{
        .type = Frontend::SwkbdType::Qwerty,
        .ok_text{},
        .left_optional_symbol_key{},
        .right_optional_symbol_key{},
        .use_prediction = false,
        .key_disable_flags{},
        .initial_cursor_position = Frontend::SwkbdInitialCursorPosition::Start,
        .header_text{},
        .sub_text{},
        .guide_text{},
        .max_text_length = 500,
        .min_text_length = 0,
        .password_mode = Frontend::SwkbdPasswordMode::Disabled,
        .text_draw_type = Frontend::SwkbdTextDrawType::Box,
        .enable_return_button = true,
        .use_utf8 = false,
        .use_blur_background = true,
        .initial_string_offset{},
        .initial_string_length = static_cast<u32>(initial_string.size()),
        .user_dictionary_offset{},
        .user_dictionary_entries{},
        .use_text_check = false,
    };

    Frontend::SwkbdConfigNew swkbd_config_new{};

    std::vector<u8> argument_data(sizeof(arguments));
    std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
    std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));

    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
    std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
    std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
                sizeof(Frontend::SwkbdConfigNew));
    std::memcpy(work_buffer.data(), initial_string.data(),
                swkbd_config.initial_string_length * sizeof(char16_t));

    queue_data.emplace_back(std::move(argument_data));
    queue_data.emplace_back(std::move(swkbd_data));
    queue_data.emplace_back(std::move(work_buffer));
}

} // namespace Service::AM