mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	service/apt: Add and implement more service commands. (#6721)
* service/apt: Add and implement more service commands. * service/apt: Implement power button. * Address review comments and fix GetApplicationRunningMode bug.
This commit is contained in:
		
							parent
							
								
									51996c54f0
								
							
						
					
					
						commit
						bb364d9bc0
					
				
					 31 changed files with 939 additions and 221 deletions
				
			
		| 
						 | 
				
			
			@ -19,7 +19,7 @@ SERVICE_CONSTRUCT_IMPL(Service::APT::AppletManager)
 | 
			
		|||
namespace Service::APT {
 | 
			
		||||
 | 
			
		||||
/// The interval at which the home button update callback will be called, 16.6ms
 | 
			
		||||
static constexpr u64 home_button_update_interval_us = 16666;
 | 
			
		||||
static constexpr u64 button_update_interval_us = 16666;
 | 
			
		||||
 | 
			
		||||
struct AppletTitleData {
 | 
			
		||||
    // There are two possible applet ids for each applet.
 | 
			
		||||
| 
						 | 
				
			
			@ -407,11 +407,56 @@ ResultCode AppletManager::Enable(AppletAttributes attributes) {
 | 
			
		|||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::Finalize(AppletId app_id) {
 | 
			
		||||
    auto slot = GetAppletSlotFromId(app_id);
 | 
			
		||||
    if (slot == AppletSlot::Error) {
 | 
			
		||||
        return {ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound,
 | 
			
		||||
                ErrorLevel::Status};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto slot_data = GetAppletSlot(slot);
 | 
			
		||||
    slot_data->Reset();
 | 
			
		||||
 | 
			
		||||
    auto inactive = active_slot == AppletSlot::Error;
 | 
			
		||||
    if (!inactive) {
 | 
			
		||||
        auto active_slot_data = GetAppletSlot(active_slot);
 | 
			
		||||
        inactive = active_slot_data->applet_id == AppletId::None ||
 | 
			
		||||
                   active_slot_data->attributes.applet_pos.Value() == AppletPos::Invalid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (inactive) {
 | 
			
		||||
        active_slot = GetAppletSlotFromPos(AppletPos::System);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 AppletManager::CountRegisteredApplet() {
 | 
			
		||||
    return static_cast<u32>(std::count_if(applet_slots.begin(), applet_slots.end(),
 | 
			
		||||
                                          [](auto& slot_data) { return slot_data.registered; }));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AppletManager::IsRegistered(AppletId app_id) {
 | 
			
		||||
    auto slot = GetAppletSlotFromId(app_id);
 | 
			
		||||
    return slot != AppletSlot::Error && GetAppletSlot(slot)->registered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultVal<AppletAttributes> AppletManager::GetAttribute(AppletId app_id) {
 | 
			
		||||
    auto slot = GetAppletSlotFromId(app_id);
 | 
			
		||||
    if (slot == AppletSlot::Error) {
 | 
			
		||||
        return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound,
 | 
			
		||||
                          ErrorLevel::Status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto slot_data = GetAppletSlot(slot);
 | 
			
		||||
    if (!slot_data->registered) {
 | 
			
		||||
        return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound,
 | 
			
		||||
                          ErrorLevel::Status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return slot_data->attributes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultVal<Notification> AppletManager::InquireNotification(AppletId app_id) {
 | 
			
		||||
    auto slot = GetAppletSlotFromId(app_id);
 | 
			
		||||
    if (slot != AppletSlot::Error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -441,6 +486,15 @@ ResultCode AppletManager::SendNotification(Notification notification) {
 | 
			
		|||
            ErrorLevel::Status};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AppletManager::SendNotificationToAll(Notification notification) {
 | 
			
		||||
    for (auto& slot_data : applet_slots) {
 | 
			
		||||
        if (slot_data.registered) {
 | 
			
		||||
            slot_data.notification = notification;
 | 
			
		||||
            slot_data.notification_event->Signal();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) {
 | 
			
		||||
    // The real APT service returns an error if there's a pending APT parameter when this function
 | 
			
		||||
    // is called.
 | 
			
		||||
| 
						 | 
				
			
			@ -594,6 +648,71 @@ ResultCode AppletManager::CancelLibraryApplet(bool app_exiting) {
 | 
			
		|||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::SendDspSleep(AppletId from_applet_id,
 | 
			
		||||
                                       std::shared_ptr<Kernel::Object> object) {
 | 
			
		||||
    auto lib_slot = GetAppletSlotFromPos(AppletPos::Library);
 | 
			
		||||
    auto lib_app_id =
 | 
			
		||||
        lib_slot != AppletSlot::Error ? GetAppletSlot(lib_slot)->applet_id : AppletId::None;
 | 
			
		||||
    if (from_applet_id == lib_app_id) {
 | 
			
		||||
        SendParameter({
 | 
			
		||||
            .sender_id = from_applet_id,
 | 
			
		||||
            .destination_id = AppletId::Application,
 | 
			
		||||
            .signal = SignalType::DspSleep,
 | 
			
		||||
            .object = std::move(object),
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto sys_lib_slot = GetAppletSlotFromPos(AppletPos::SysLibrary);
 | 
			
		||||
    auto sys_lib_app_id =
 | 
			
		||||
        sys_lib_slot != AppletSlot::Error ? GetAppletSlot(sys_lib_slot)->applet_id : AppletId::None;
 | 
			
		||||
    if (from_applet_id == sys_lib_app_id) {
 | 
			
		||||
        auto sys_slot = GetAppletSlotFromPos(AppletPos::System);
 | 
			
		||||
        auto sys_app_id =
 | 
			
		||||
            sys_slot != AppletSlot::Error ? GetAppletSlot(sys_slot)->applet_id : AppletId::None;
 | 
			
		||||
        SendParameter({
 | 
			
		||||
            .sender_id = from_applet_id,
 | 
			
		||||
            .destination_id = sys_app_id,
 | 
			
		||||
            .signal = SignalType::DspSleep,
 | 
			
		||||
            .object = std::move(object),
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::SendDspWakeUp(AppletId from_applet_id,
 | 
			
		||||
                                        std::shared_ptr<Kernel::Object> object) {
 | 
			
		||||
    auto lib_slot = GetAppletSlotFromPos(AppletPos::Library);
 | 
			
		||||
    auto lib_app_id =
 | 
			
		||||
        lib_slot != AppletSlot::Error ? GetAppletSlot(lib_slot)->applet_id : AppletId::None;
 | 
			
		||||
    if (from_applet_id == lib_app_id) {
 | 
			
		||||
        SendParameter({
 | 
			
		||||
            .sender_id = from_applet_id,
 | 
			
		||||
            .destination_id = AppletId::Application,
 | 
			
		||||
            .signal = SignalType::DspSleep,
 | 
			
		||||
            .object = std::move(object),
 | 
			
		||||
        });
 | 
			
		||||
    } else {
 | 
			
		||||
        auto sys_lib_slot = GetAppletSlotFromPos(AppletPos::SysLibrary);
 | 
			
		||||
        auto sys_lib_app_id = sys_lib_slot != AppletSlot::Error
 | 
			
		||||
                                  ? GetAppletSlot(sys_lib_slot)->applet_id
 | 
			
		||||
                                  : AppletId::None;
 | 
			
		||||
        if (from_applet_id == sys_lib_app_id) {
 | 
			
		||||
            auto sys_slot = GetAppletSlotFromPos(AppletPos::System);
 | 
			
		||||
            auto sys_app_id =
 | 
			
		||||
                sys_slot != AppletSlot::Error ? GetAppletSlot(sys_slot)->applet_id : AppletId::None;
 | 
			
		||||
            SendParameter({
 | 
			
		||||
                .sender_id = from_applet_id,
 | 
			
		||||
                .destination_id = sys_app_id,
 | 
			
		||||
                .signal = SignalType::DspSleep,
 | 
			
		||||
                .object = std::move(object),
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::PrepareToStartSystemApplet(AppletId applet_id) {
 | 
			
		||||
    // The real APT service returns an error if there's a pending APT parameter when this function
 | 
			
		||||
    // is called.
 | 
			
		||||
| 
						 | 
				
			
			@ -963,10 +1082,7 @@ ResultVal<AppletManager::AppletInfo> AppletManager::GetAppletInfo(AppletId app_i
 | 
			
		|||
                          ErrorLevel::Status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: Basic heuristic to guess media type, needs proper implementation.
 | 
			
		||||
    auto media_type = ((slot_data->title_id >> 32) & 0xFFFFFFFF) == 0x00040000
 | 
			
		||||
                          ? Service::FS::MediaType::SDMC
 | 
			
		||||
                          : Service::FS::MediaType::NAND;
 | 
			
		||||
    auto media_type = Service::AM::GetTitleMediaType(slot_data->title_id);
 | 
			
		||||
    return AppletInfo{
 | 
			
		||||
        .title_id = slot_data->title_id,
 | 
			
		||||
        .media_type = media_type,
 | 
			
		||||
| 
						 | 
				
			
			@ -976,6 +1092,61 @@ ResultVal<AppletManager::AppletInfo> AppletManager::GetAppletInfo(AppletId app_i
 | 
			
		|||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultVal<Service::FS::MediaType> AppletManager::Unknown54(u32 in_param) {
 | 
			
		||||
    auto slot_data = GetAppletSlot(AppletSlot::Application);
 | 
			
		||||
    if (slot_data->applet_id == AppletId::None) {
 | 
			
		||||
        return ResultCode{ErrCodes::AppNotRunning, ErrorModule::Applet, ErrorSummary::InvalidState,
 | 
			
		||||
                          ErrorLevel::Permanent};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (in_param >= 0x80) {
 | 
			
		||||
        // TODO: Add error description name when the parameter is known.
 | 
			
		||||
        return ResultCode{10, ErrorModule::Applet, ErrorSummary::InvalidArgument,
 | 
			
		||||
                          ErrorLevel::Usage};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: Figure out what this logic is actually for.
 | 
			
		||||
    auto check_target =
 | 
			
		||||
        in_param >= 0x40 ? Service::FS::MediaType::GameCard : Service::FS::MediaType::SDMC;
 | 
			
		||||
    auto check_update = in_param == 0x01 || in_param == 0x42;
 | 
			
		||||
 | 
			
		||||
    auto app_media_type = Service::AM::GetTitleMediaType(slot_data->title_id);
 | 
			
		||||
    auto app_update_media_type =
 | 
			
		||||
        Service::AM::GetTitleMediaType(Service::AM::GetTitleUpdateId(slot_data->title_id));
 | 
			
		||||
    if (app_media_type == check_target || (check_update && app_update_media_type == check_target)) {
 | 
			
		||||
        return Service::FS::MediaType::SDMC;
 | 
			
		||||
    } else {
 | 
			
		||||
        return Service::FS::MediaType::NAND;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TargetPlatform AppletManager::GetTargetPlatform() {
 | 
			
		||||
    if (Settings::values.is_new_3ds.GetValue() && !new_3ds_mode_blocked) {
 | 
			
		||||
        return TargetPlatform::New3ds;
 | 
			
		||||
    } else {
 | 
			
		||||
        return TargetPlatform::Old3ds;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ApplicationRunningMode AppletManager::GetApplicationRunningMode() {
 | 
			
		||||
    auto slot_data = GetAppletSlot(AppletSlot::Application);
 | 
			
		||||
    if (slot_data->applet_id == AppletId::None) {
 | 
			
		||||
        return ApplicationRunningMode::NoApplication;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // APT checks whether the system is a New 3DS and the 804MHz CPU speed is enabled to determine
 | 
			
		||||
    // the result.
 | 
			
		||||
    auto new_3ds_mode = GetTargetPlatform() == TargetPlatform::New3ds &&
 | 
			
		||||
                        system.Kernel().GetNew3dsHwCapabilities().enable_804MHz_cpu;
 | 
			
		||||
    if (slot_data->registered) {
 | 
			
		||||
        return new_3ds_mode ? ApplicationRunningMode::New3dsRegistered
 | 
			
		||||
                            : ApplicationRunningMode::Old3dsRegistered;
 | 
			
		||||
    } else {
 | 
			
		||||
        return new_3ds_mode ? ApplicationRunningMode::New3dsUnregistered
 | 
			
		||||
                            : ApplicationRunningMode::Old3dsUnregistered;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::PrepareToDoApplicationJump(u64 title_id, FS::MediaType media_type,
 | 
			
		||||
                                                     ApplicationJumpFlags flags) {
 | 
			
		||||
    // A running application can not launch another application directly because the applet state
 | 
			
		||||
| 
						 | 
				
			
			@ -988,11 +1159,8 @@ ResultCode AppletManager::PrepareToDoApplicationJump(u64 title_id, FS::MediaType
 | 
			
		|||
    // Save the title data to send it to the Home Menu when DoApplicationJump is called.
 | 
			
		||||
    auto application_slot_data = GetAppletSlot(AppletSlot::Application);
 | 
			
		||||
    app_jump_parameters.current_title_id = application_slot_data->title_id;
 | 
			
		||||
    // TODO: Basic heuristic to guess media type, needs proper implementation.
 | 
			
		||||
    app_jump_parameters.current_media_type =
 | 
			
		||||
        ((application_slot_data->title_id >> 32) & 0xFFFFFFFF) == 0x00040000
 | 
			
		||||
            ? Service::FS::MediaType::SDMC
 | 
			
		||||
            : Service::FS::MediaType::NAND;
 | 
			
		||||
        Service::AM::GetTitleMediaType(application_slot_data->title_id);
 | 
			
		||||
    if (flags == ApplicationJumpFlags::UseCurrentParameters) {
 | 
			
		||||
        app_jump_parameters.next_title_id = app_jump_parameters.current_title_id;
 | 
			
		||||
        app_jump_parameters.next_media_type = app_jump_parameters.current_media_type;
 | 
			
		||||
| 
						 | 
				
			
			@ -1055,19 +1223,8 @@ ResultCode AppletManager::DoApplicationJump(const DeliverArg& arg) {
 | 
			
		|||
        return RESULT_SUCCESS;
 | 
			
		||||
        */
 | 
			
		||||
 | 
			
		||||
        auto new_path = Service::AM::GetTitleContentPath(app_jump_parameters.next_media_type,
 | 
			
		||||
                                                         app_jump_parameters.next_title_id);
 | 
			
		||||
        if (new_path.empty() || !FileUtil::Exists(new_path)) {
 | 
			
		||||
            // TODO: This can happen if the requested title is not installed. Need a way to find
 | 
			
		||||
            // non-installed titles in the game list.
 | 
			
		||||
            LOG_CRITICAL(
 | 
			
		||||
                Service_APT,
 | 
			
		||||
                "Failed to find title during application jump: {} Resetting current title instead.",
 | 
			
		||||
                new_path);
 | 
			
		||||
            new_path.clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        system.RequestReset(new_path);
 | 
			
		||||
        NS::RebootToTitle(system, app_jump_parameters.next_media_type,
 | 
			
		||||
                          app_jump_parameters.next_title_id);
 | 
			
		||||
        return RESULT_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1126,13 +1283,14 @@ ResultCode AppletManager::StartApplication(const std::vector<u8>& parameter,
 | 
			
		|||
    app_start_parameters.reset();
 | 
			
		||||
 | 
			
		||||
    if (!paused) {
 | 
			
		||||
        return WakeupApplication();
 | 
			
		||||
        return WakeupApplication(nullptr, {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode AppletManager::WakeupApplication() {
 | 
			
		||||
ResultCode AppletManager::WakeupApplication(std::shared_ptr<Kernel::Object> object,
 | 
			
		||||
                                            const std::vector<u8>& buffer) {
 | 
			
		||||
    // Send a Wakeup signal via the apt parameter to the application once it registers itself.
 | 
			
		||||
    // The real APT service does this by spin waiting on another thread until the application is
 | 
			
		||||
    // registered.
 | 
			
		||||
| 
						 | 
				
			
			@ -1140,6 +1298,8 @@ ResultCode AppletManager::WakeupApplication() {
 | 
			
		|||
        .sender_id = AppletId::HomeMenu,
 | 
			
		||||
        .destination_id = AppletId::Application,
 | 
			
		||||
        .signal = SignalType::Wakeup,
 | 
			
		||||
        .object = std::move(object),
 | 
			
		||||
        .buffer = buffer,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return RESULT_SUCCESS;
 | 
			
		||||
| 
						 | 
				
			
			@ -1248,27 +1408,38 @@ void AppletManager::CaptureFrameBuffers() {
 | 
			
		|||
void AppletManager::LoadInputDevices() {
 | 
			
		||||
    home_button = Input::CreateDevice<Input::ButtonDevice>(
 | 
			
		||||
        Settings::values.current_input_profile.buttons[Settings::NativeButton::Home]);
 | 
			
		||||
    power_button = Input::CreateDevice<Input::ButtonDevice>(
 | 
			
		||||
        Settings::values.current_input_profile.buttons[Settings::NativeButton::Power]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AppletManager::HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) {
 | 
			
		||||
void AppletManager::ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late) {
 | 
			
		||||
    if (is_device_reload_pending.exchange(false)) {
 | 
			
		||||
        LoadInputDevices();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const bool state = home_button->GetStatus();
 | 
			
		||||
    // NOTE: We technically do support loading and jumping to home menu even if it isn't
 | 
			
		||||
    // initially registered. However since the home menu suspend is not bug-free, we don't
 | 
			
		||||
    // want normal users who didn't launch the home menu accidentally pressing the home
 | 
			
		||||
    // button binding and freezing their game, so for now, gate it to only environments
 | 
			
		||||
    // where the home menu was already loaded by the user (last condition).
 | 
			
		||||
    if (state && !last_home_button_state && GetAppletSlot(AppletSlot::HomeMenu)->registered) {
 | 
			
		||||
        SendNotification(Notification::HomeButtonSingle);
 | 
			
		||||
 | 
			
		||||
    if (GetAppletSlot(AppletSlot::HomeMenu)->registered) {
 | 
			
		||||
        const bool home_state = home_button->GetStatus();
 | 
			
		||||
        if (home_state && !last_home_button_state) {
 | 
			
		||||
            SendNotification(Notification::HomeButtonSingle);
 | 
			
		||||
        }
 | 
			
		||||
        last_home_button_state = home_state;
 | 
			
		||||
 | 
			
		||||
        const bool power_state = power_button->GetStatus();
 | 
			
		||||
        if (power_state && !last_power_button_state) {
 | 
			
		||||
            SendNotificationToAll(Notification::PowerButtonClick);
 | 
			
		||||
        }
 | 
			
		||||
        last_power_button_state = power_state;
 | 
			
		||||
    }
 | 
			
		||||
    last_home_button_state = state;
 | 
			
		||||
 | 
			
		||||
    // Reschedule recurrent event
 | 
			
		||||
    Core::System::GetInstance().CoreTiming().ScheduleEvent(
 | 
			
		||||
        usToCycles(home_button_update_interval_us) - cycles_late, home_button_update_event);
 | 
			
		||||
    system.CoreTiming().ScheduleEvent(usToCycles(button_update_interval_us) - cycles_late,
 | 
			
		||||
                                      button_update_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppletManager::AppletManager(Core::System& system) : system(system) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1286,12 +1457,11 @@ AppletManager::AppletManager(Core::System& system) : system(system) {
 | 
			
		|||
            system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Parameter");
 | 
			
		||||
    }
 | 
			
		||||
    HLE::Applets::Init();
 | 
			
		||||
    home_button_update_event = Core::System::GetInstance().CoreTiming().RegisterEvent(
 | 
			
		||||
        "Home Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) {
 | 
			
		||||
            HomeButtonUpdateEvent(user_data, cycles_late);
 | 
			
		||||
    button_update_event = system.CoreTiming().RegisterEvent(
 | 
			
		||||
        "APT Button Update Event", [this](std::uintptr_t user_data, s64 cycles_late) {
 | 
			
		||||
            ButtonUpdateEvent(user_data, cycles_late);
 | 
			
		||||
        });
 | 
			
		||||
    Core::System::GetInstance().CoreTiming().ScheduleEvent(
 | 
			
		||||
        usToCycles(home_button_update_interval_us), home_button_update_event);
 | 
			
		||||
    system.CoreTiming().ScheduleEvent(usToCycles(button_update_interval_us), button_update_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppletManager::~AppletManager() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,6 +99,21 @@ enum class AppletId : u32 {
 | 
			
		|||
    Memolib2 = 0x409,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Application Old/New 3DS target platforms
 | 
			
		||||
enum class TargetPlatform : u8 {
 | 
			
		||||
    Old3ds = 0,
 | 
			
		||||
    New3ds = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Application Old/New 3DS running modes
 | 
			
		||||
enum class ApplicationRunningMode : u8 {
 | 
			
		||||
    NoApplication = 0,
 | 
			
		||||
    Old3dsRegistered = 1,
 | 
			
		||||
    New3dsRegistered = 2,
 | 
			
		||||
    Old3dsUnregistered = 3,
 | 
			
		||||
    New3dsUnregistered = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Holds information about the parameters used in Send/Glance/ReceiveParameter
 | 
			
		||||
struct MessageParameter {
 | 
			
		||||
    AppletId sender_id = AppletId::None;
 | 
			
		||||
| 
						 | 
				
			
			@ -256,10 +271,14 @@ public:
 | 
			
		|||
    ResultVal<InitializeResult> Initialize(AppletId app_id, AppletAttributes attributes);
 | 
			
		||||
 | 
			
		||||
    ResultCode Enable(AppletAttributes attributes);
 | 
			
		||||
    ResultCode Finalize(AppletId app_id);
 | 
			
		||||
    u32 CountRegisteredApplet();
 | 
			
		||||
    bool IsRegistered(AppletId app_id);
 | 
			
		||||
    ResultVal<AppletAttributes> GetAttribute(AppletId app_id);
 | 
			
		||||
 | 
			
		||||
    ResultVal<Notification> InquireNotification(AppletId app_id);
 | 
			
		||||
    ResultCode SendNotification(Notification notification);
 | 
			
		||||
    void SendNotificationToAll(Notification notification);
 | 
			
		||||
 | 
			
		||||
    ResultCode PrepareToStartLibraryApplet(AppletId applet_id);
 | 
			
		||||
    ResultCode PreloadLibraryApplet(AppletId applet_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -271,6 +290,9 @@ public:
 | 
			
		|||
                                  const std::vector<u8>& buffer);
 | 
			
		||||
    ResultCode CancelLibraryApplet(bool app_exiting);
 | 
			
		||||
 | 
			
		||||
    ResultCode SendDspSleep(AppletId from_applet_id, std::shared_ptr<Kernel::Object> object);
 | 
			
		||||
    ResultCode SendDspWakeUp(AppletId from_applet_id, std::shared_ptr<Kernel::Object> object);
 | 
			
		||||
 | 
			
		||||
    ResultCode PrepareToStartSystemApplet(AppletId applet_id);
 | 
			
		||||
    ResultCode StartSystemApplet(AppletId applet_id, std::shared_ptr<Kernel::Object> object,
 | 
			
		||||
                                 const std::vector<u8>& buffer);
 | 
			
		||||
| 
						 | 
				
			
			@ -294,8 +316,10 @@ public:
 | 
			
		|||
                                          ApplicationJumpFlags flags);
 | 
			
		||||
    ResultCode DoApplicationJump(const DeliverArg& arg);
 | 
			
		||||
 | 
			
		||||
    boost::optional<DeliverArg> ReceiveDeliverArg() const {
 | 
			
		||||
        return deliver_arg;
 | 
			
		||||
    boost::optional<DeliverArg> ReceiveDeliverArg() {
 | 
			
		||||
        auto arg = deliver_arg;
 | 
			
		||||
        deliver_arg = boost::none;
 | 
			
		||||
        return arg;
 | 
			
		||||
    }
 | 
			
		||||
    void SetDeliverArg(boost::optional<DeliverArg> arg) {
 | 
			
		||||
        deliver_arg = std::move(arg);
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +348,8 @@ public:
 | 
			
		|||
    ResultCode PrepareToStartApplication(u64 title_id, FS::MediaType media_type);
 | 
			
		||||
    ResultCode StartApplication(const std::vector<u8>& parameter, const std::vector<u8>& hmac,
 | 
			
		||||
                                bool paused);
 | 
			
		||||
    ResultCode WakeupApplication();
 | 
			
		||||
    ResultCode WakeupApplication(std::shared_ptr<Kernel::Object> object,
 | 
			
		||||
                                 const std::vector<u8>& buffer);
 | 
			
		||||
    ResultCode CancelApplication();
 | 
			
		||||
 | 
			
		||||
    struct AppletManInfo {
 | 
			
		||||
| 
						 | 
				
			
			@ -349,6 +374,10 @@ public:
 | 
			
		|||
        return app_jump_parameters;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ResultVal<Service::FS::MediaType> Unknown54(u32 in_param);
 | 
			
		||||
    TargetPlatform GetTargetPlatform();
 | 
			
		||||
    ApplicationRunningMode GetApplicationRunningMode();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    /// APT lock retrieved via GetLockHandle.
 | 
			
		||||
    std::shared_ptr<Kernel::Mutex> lock;
 | 
			
		||||
| 
						 | 
				
			
			@ -427,10 +456,16 @@ private:
 | 
			
		|||
    bool application_cancelled = false;
 | 
			
		||||
    AppletSlot application_close_target = AppletSlot::Error;
 | 
			
		||||
 | 
			
		||||
    Core::TimingEventType* home_button_update_event;
 | 
			
		||||
    // This flag is used to determine if an app that supports New 3DS capabilities should use them.
 | 
			
		||||
    // It also affects the results of APT:GetTargetPlatform and APT:GetApplicationRunningMode.
 | 
			
		||||
    bool new_3ds_mode_blocked = false;
 | 
			
		||||
 | 
			
		||||
    Core::TimingEventType* button_update_event;
 | 
			
		||||
    std::atomic<bool> is_device_reload_pending{true};
 | 
			
		||||
    std::unique_ptr<Input::ButtonDevice> home_button;
 | 
			
		||||
    std::unique_ptr<Input::ButtonDevice> power_button;
 | 
			
		||||
    bool last_home_button_state = false;
 | 
			
		||||
    bool last_power_button_state = false;
 | 
			
		||||
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +490,7 @@ private:
 | 
			
		|||
    void CaptureFrameBuffers();
 | 
			
		||||
 | 
			
		||||
    void LoadInputDevices();
 | 
			
		||||
    void HomeButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late);
 | 
			
		||||
    void ButtonUpdateEvent(std::uintptr_t user_data, s64 cycles_late);
 | 
			
		||||
 | 
			
		||||
    template <class Archive>
 | 
			
		||||
    void serialize(Archive& ar, const unsigned int file_version) {
 | 
			
		||||
| 
						 | 
				
			
			@ -474,6 +509,7 @@ private:
 | 
			
		|||
            ar& ordered_to_close_application;
 | 
			
		||||
            ar& application_cancelled;
 | 
			
		||||
            ar& application_close_target;
 | 
			
		||||
            ar& new_3ds_mode_blocked;
 | 
			
		||||
            ar& lock;
 | 
			
		||||
            ar& capture_info;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,16 +16,19 @@
 | 
			
		|||
#include "core/hle/kernel/mutex.h"
 | 
			
		||||
#include "core/hle/kernel/shared_memory.h"
 | 
			
		||||
#include "core/hle/romfs.h"
 | 
			
		||||
#include "core/hle/service/am/am.h"
 | 
			
		||||
#include "core/hle/service/apt/applet_manager.h"
 | 
			
		||||
#include "core/hle/service/apt/apt.h"
 | 
			
		||||
#include "core/hle/service/apt/apt_a.h"
 | 
			
		||||
#include "core/hle/service/apt/apt_s.h"
 | 
			
		||||
#include "core/hle/service/apt/apt_u.h"
 | 
			
		||||
#include "core/hle/service/apt/bcfnt/bcfnt.h"
 | 
			
		||||
#include "core/hle/service/apt/ns.h"
 | 
			
		||||
#include "core/hle/service/apt/ns_c.h"
 | 
			
		||||
#include "core/hle/service/apt/ns_s.h"
 | 
			
		||||
#include "core/hle/service/cfg/cfg.h"
 | 
			
		||||
#include "core/hle/service/fs/archive.h"
 | 
			
		||||
#include "core/hle/service/fs/fs_user.h"
 | 
			
		||||
#include "core/hle/service/ptm/ptm.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
#include "core/hw/aes/ccm.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +44,6 @@ void Module::serialize(Archive& ar, const unsigned int file_version) {
 | 
			
		|||
    ar& shared_font_loaded;
 | 
			
		||||
    ar& shared_font_relocated;
 | 
			
		||||
    ar& cpu_percent;
 | 
			
		||||
    ar& unknown_ns_state_field;
 | 
			
		||||
    ar& screen_capture_post_permission;
 | 
			
		||||
    ar& applet_manager;
 | 
			
		||||
    if (file_version > 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -90,14 +92,19 @@ void Module::NSInterface::RebootSystem(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    const auto title_id = rp.Pop<u64>();
 | 
			
		||||
    const auto media_type = static_cast<FS::MediaType>(rp.Pop<u8>());
 | 
			
		||||
    rp.Skip(1, false); // Skip padding
 | 
			
		||||
    // TODO: Utilize requested memory type.
 | 
			
		||||
    const auto mem_type = rp.Pop<u8>();
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_APT,
 | 
			
		||||
                "called launch_title={}, title_id={:016X}, media_type={:02X}, mem_type={:02X}",
 | 
			
		||||
                launch_title, title_id, media_type, mem_type);
 | 
			
		||||
 | 
			
		||||
    // TODO: Implement loading a specific title.
 | 
			
		||||
    apt->system.RequestReset();
 | 
			
		||||
    // TODO: Handle mem type.
 | 
			
		||||
    if (launch_title) {
 | 
			
		||||
        NS::RebootToTitle(apt->system, media_type, title_id);
 | 
			
		||||
    } else {
 | 
			
		||||
        apt->system.RequestReset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
| 
						 | 
				
			
			@ -371,6 +378,16 @@ void Module::APTInterface::Enable(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    rb.Push(apt->applet_manager->Enable(attributes));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::Finalize(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto applet_id = rp.PopEnum<AppletId>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called applet_id={:08X}", applet_id);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(apt->applet_manager->Finalize(applet_id));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetAppletManInfo(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    auto applet_pos = rp.PopEnum<AppletPos>();
 | 
			
		||||
| 
						 | 
				
			
			@ -391,6 +408,16 @@ void Module::APTInterface::GetAppletManInfo(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::CountRegisteredApplet(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.Push(apt->applet_manager->CountRegisteredApplet());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::IsRegistered(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto app_id = rp.PopEnum<AppletId>();
 | 
			
		||||
| 
						 | 
				
			
			@ -402,6 +429,23 @@ void Module::APTInterface::IsRegistered(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    LOG_DEBUG(Service_APT, "called app_id={:#010X}", app_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetAttribute(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto app_id = rp.PopEnum<AppletId>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called app_id={:#010X}", app_id);
 | 
			
		||||
 | 
			
		||||
    auto applet_attr = apt->applet_manager->GetAttribute(app_id);
 | 
			
		||||
    if (applet_attr.Failed()) {
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
        rb.Push(applet_attr.Code());
 | 
			
		||||
    } else {
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.Push(applet_attr.Unwrap().raw);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::InquireNotification(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto app_id = rp.PopEnum<AppletId>();
 | 
			
		||||
| 
						 | 
				
			
			@ -557,6 +601,21 @@ void Module::APTInterface::GetProgramIdOnApplicationJump(Kernel::HLERequestConte
 | 
			
		|||
    rb.Push(static_cast<u8>(parameters.next_media_type));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::SendDeliverArg(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto param_size = rp.Pop<u32>();
 | 
			
		||||
    const auto hmac_size = rp.Pop<u32>();
 | 
			
		||||
    const auto param = rp.PopStaticBuffer();
 | 
			
		||||
    const auto hmac = rp.PopStaticBuffer();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called param_size={:08X}, hmac_size={:08X}", param_size, hmac_size);
 | 
			
		||||
 | 
			
		||||
    apt->applet_manager->SetDeliverArg(DeliverArg{param, hmac});
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::ReceiveDeliverArg(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto param_size = rp.Pop<u32>();
 | 
			
		||||
| 
						 | 
				
			
			@ -611,7 +670,7 @@ void Module::APTInterface::WakeupApplication(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(apt->applet_manager->WakeupApplication());
 | 
			
		||||
    rb.Push(apt->applet_manager->WakeupApplication(nullptr, {}));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::CancelApplication(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
| 
						 | 
				
			
			@ -856,6 +915,28 @@ void Module::APTInterface::OrderToCloseSystemApplet(Kernel::HLERequestContext& c
 | 
			
		|||
    rb.Push(apt->applet_manager->OrderToCloseSystemApplet());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::SendDspSleep(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto from_app_id = rp.PopEnum<AppletId>();
 | 
			
		||||
    const auto object = rp.PopGenericObject();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called, from_app_id={:08X}", from_app_id);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(apt->applet_manager->SendDspSleep(from_app_id, object));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::SendDspWakeUp(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto from_app_id = rp.PopEnum<AppletId>();
 | 
			
		||||
    const auto object = rp.PopGenericObject();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called, from_app_id={:08X}", from_app_id);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(apt->applet_manager->SendDspWakeUp(from_app_id, object));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::PrepareToJumpToHomeMenu(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -972,29 +1053,124 @@ void Module::APTInterface::GetCaptureInfo(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    rb.PushStaticBuffer(std::move(screen_capture_buffer), 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::SetScreenCapPostPermission(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
void Module::APTInterface::Unknown54(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    auto in_param = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called, screen_capture_post_permission={}",
 | 
			
		||||
              apt->screen_capture_post_permission);
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called, in_param={}", in_param);
 | 
			
		||||
 | 
			
		||||
    apt->screen_capture_post_permission = static_cast<ScreencapPostPermission>(rp.Pop<u32>() & 0xF);
 | 
			
		||||
    auto media_type = apt->applet_manager->Unknown54(in_param);
 | 
			
		||||
    if (media_type.Failed()) {
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
        rb.Push(media_type.Code());
 | 
			
		||||
    } else {
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.PushEnum(media_type.Unwrap());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::SetScreenCapturePostPermission(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    auto permission = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called, permission={}", permission);
 | 
			
		||||
 | 
			
		||||
    apt->screen_capture_post_permission = static_cast<ScreencapPostPermission>(permission & 0xF);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS); // No error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetScreenCapPostPermission(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
void Module::APTInterface::GetScreenCapturePostPermission(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "(STUBBED) called, screen_capture_post_permission={}",
 | 
			
		||||
              apt->screen_capture_post_permission);
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS); // No error
 | 
			
		||||
    rb.Push(static_cast<u32>(apt->screen_capture_post_permission));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::WakeupApplication2(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto buffer_size = rp.Pop<u32>();
 | 
			
		||||
    const auto object = rp.PopGenericObject();
 | 
			
		||||
    const auto buffer = rp.PopStaticBuffer();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called buffer_size={:#010X}", buffer_size);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(apt->applet_manager->WakeupApplication(object, buffer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetProgramId(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto process_id = rp.PopPID();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called process_id={}", process_id);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
 | 
			
		||||
    auto fs_user =
 | 
			
		||||
        Core::System::GetInstance().ServiceManager().GetService<Service::FS::FS_USER>("fs:USER");
 | 
			
		||||
    ASSERT_MSG(fs_user != nullptr, "fs:USER service is missing.");
 | 
			
		||||
 | 
			
		||||
    auto program_info_result = fs_user->GetProgramLaunchInfo(process_id);
 | 
			
		||||
    if (program_info_result.Failed()) {
 | 
			
		||||
        // On failure, APT still returns a success result with a program ID of 0.
 | 
			
		||||
        rb.Push<u64>(0);
 | 
			
		||||
    } else {
 | 
			
		||||
        rb.Push(program_info_result.Unwrap().program_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetProgramInfo(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto title_id = rp.Pop<u64>();
 | 
			
		||||
    const auto media_type = static_cast<FS::MediaType>(rp.Pop<u8>());
 | 
			
		||||
    rp.Skip(1, false); // Skip padding
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_APT, "called title_id={:016X}, media_type={:02X}", title_id, media_type);
 | 
			
		||||
 | 
			
		||||
    std::string path = Service::AM::GetTitleContentPath(media_type, title_id);
 | 
			
		||||
    auto loader = Loader::GetLoader(path);
 | 
			
		||||
    if (!loader) {
 | 
			
		||||
        LOG_WARNING(Service_APT, "Could not find .app for title 0x{:016x}", title_id);
 | 
			
		||||
 | 
			
		||||
        // TODO: Proper error code
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
        rb.Push(RESULT_UNKNOWN);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto memory_mode = loader->LoadKernelMemoryMode();
 | 
			
		||||
    if (memory_mode.second != Loader::ResultStatus::Success || !memory_mode.first) {
 | 
			
		||||
        LOG_ERROR(Service_APT, "Could not load memory mode for title 0x{:016x}", title_id);
 | 
			
		||||
 | 
			
		||||
        // TODO: Proper error code
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
        rb.Push(RESULT_UNKNOWN);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto core_version = loader->LoadCoreVersion();
 | 
			
		||||
    if (core_version.second != Loader::ResultStatus::Success || !core_version.first) {
 | 
			
		||||
        LOG_ERROR(Service_APT, "Could not load core version for title 0x{:016x}", title_id);
 | 
			
		||||
 | 
			
		||||
        // TODO: Proper error code
 | 
			
		||||
        IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
        rb.Push(RESULT_UNKNOWN);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.Push(static_cast<u8>(memory_mode.first.value()));
 | 
			
		||||
    rb.Push(core_version.first.value());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetAppletInfo(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto app_id = rp.PopEnum<AppletId>();
 | 
			
		||||
| 
						 | 
				
			
			@ -1154,37 +1330,83 @@ void Module::APTInterface::Unwrap(Kernel::HLERequestContext& ctx) {
 | 
			
		|||
    rb.PushMappedBuffer(output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::CheckNew3DSApp(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
void Module::APTInterface::Reboot(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
    const auto title_id = rp.Pop<u64>();
 | 
			
		||||
    const auto media_type = static_cast<FS::MediaType>(rp.Pop<u8>());
 | 
			
		||||
    rp.Skip(1, false); // Skip padding
 | 
			
		||||
    const auto mem_type = rp.Pop<u8>();
 | 
			
		||||
    const auto firm_tid_low = rp.Pop<u32>();
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_APT,
 | 
			
		||||
                "called title_id={:016X}, media_type={:02X}, mem_type={:02X}, firm_tid_low={:08X}",
 | 
			
		||||
                title_id, media_type, mem_type, firm_tid_low);
 | 
			
		||||
 | 
			
		||||
    // TODO: Handle mem type and FIRM TID low.
 | 
			
		||||
    NS::RebootToTitle(apt->system, media_type, title_id);
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::HardwareResetAsync(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_APT, "(STUBBED) called");
 | 
			
		||||
    LOG_WARNING(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    apt->system.RequestReset();
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::GetTargetPlatform(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
    if (apt->unknown_ns_state_field) {
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.Push<u32>(0);
 | 
			
		||||
    } else {
 | 
			
		||||
        PTM::CheckNew3DS(rb);
 | 
			
		||||
    }
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushEnum(apt->applet_manager->GetTargetPlatform());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::CheckNew3DS(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_APT, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    PTM::CheckNew3DS(rb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::Unknown0x0103(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
void Module::APTInterface::GetApplicationRunningMode(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_APT, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.Push<u8>(Settings::values.is_new_3ds ? 2 : 1);
 | 
			
		||||
    rb.PushEnum(apt->applet_manager->GetApplicationRunningMode());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::IsStandardMemoryLayout(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp(ctx);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_APT, "called");
 | 
			
		||||
 | 
			
		||||
    bool is_standard;
 | 
			
		||||
    if (Settings::values.is_new_3ds) {
 | 
			
		||||
        // Memory layout is standard if it is not NewDev1 (178MB)
 | 
			
		||||
        is_standard = apt->system.Kernel().GetNew3dsHwCapabilities().memory_mode !=
 | 
			
		||||
                      Kernel::New3dsMemoryMode::NewDev1;
 | 
			
		||||
    } else {
 | 
			
		||||
        // Memory layout is standard if it is Prod (64MB)
 | 
			
		||||
        is_standard = apt->system.Kernel().GetMemoryMode() == Kernel::MemoryMode::Prod;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.Push(is_standard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Module::APTInterface::IsTitleAllowed(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -214,6 +214,15 @@ public:
 | 
			
		|||
         */
 | 
			
		||||
        void Enable(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::Finalize service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      1 : Applet ID
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         */
 | 
			
		||||
        void Finalize(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::GetAppletManInfo service function.
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
| 
						 | 
				
			
			@ -241,6 +250,15 @@ public:
 | 
			
		|||
         */
 | 
			
		||||
        void GetAppletInfo(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::CountRegisteredApplet service function
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      0 : Return header
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         *      2 : Number of registered applets
 | 
			
		||||
         */
 | 
			
		||||
        void CountRegisteredApplet(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::IsRegistered service function. This returns whether the specified AppID is
 | 
			
		||||
         * registered with NS yet. An AppID is "registered" once the process associated with the
 | 
			
		||||
| 
						 | 
				
			
			@ -257,6 +275,17 @@ public:
 | 
			
		|||
         */
 | 
			
		||||
        void IsRegistered(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::GetAttribute service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      1 : AppID
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      0 : Return header
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         *      2 : Applet Attributes
 | 
			
		||||
         */
 | 
			
		||||
        void GetAttribute(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        void InquireNotification(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
| 
						 | 
				
			
			@ -596,6 +625,21 @@ public:
 | 
			
		|||
         */
 | 
			
		||||
        void GetProgramIdOnApplicationJump(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::SendDeliverArg service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      0 : Command header [0x00340084]
 | 
			
		||||
         *      1 : Parameter Size (capped to 0x300)
 | 
			
		||||
         *      2 : HMAC Size (capped to 0x20)
 | 
			
		||||
         *      3 : (Parameter Size << 14) | 2
 | 
			
		||||
         *      4 : Input buffer for Parameter
 | 
			
		||||
         *      5 : (HMAC Size << 14) | 0x802
 | 
			
		||||
         *      6 : Input buffer for HMAC
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         */
 | 
			
		||||
        void SendDeliverArg(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::ReceiveDeliverArg service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
| 
						 | 
				
			
			@ -687,6 +731,30 @@ public:
 | 
			
		|||
         */
 | 
			
		||||
        void OrderToCloseSystemApplet(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::SendDspSleep service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      1 : Source App ID
 | 
			
		||||
         *      2 : Handle translation header (0x0)
 | 
			
		||||
         *      3 : Handle parameter
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      0 : Header code
 | 
			
		||||
         *      1 : Result code
 | 
			
		||||
         */
 | 
			
		||||
        void SendDspSleep(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::SendDspWakeUp service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      1 : Source App ID
 | 
			
		||||
         *      2 : Handle translation header (0x0)
 | 
			
		||||
         *      3 : Handle parameter
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      0 : Header code
 | 
			
		||||
         *      1 : Result code
 | 
			
		||||
         */
 | 
			
		||||
        void SendDspWakeUp(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::PrepareToJumpToHomeMenu service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
| 
						 | 
				
			
			@ -818,27 +886,97 @@ public:
 | 
			
		|||
        void GetStartupArgument(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::SetScreenCapPostPermission service function
 | 
			
		||||
         * APT::Unknown54 service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      0 : Header Code[0x00540040]
 | 
			
		||||
         *      1 : Unknown
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         *      2 : Media Type
 | 
			
		||||
         */
 | 
			
		||||
        void Unknown54(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::SetScreenCapturePostPermission service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      0 : Header Code[0x00550040]
 | 
			
		||||
         *      1 : u8 The screenshot posting permission
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         */
 | 
			
		||||
        void SetScreenCapPostPermission(Kernel::HLERequestContext& ctx);
 | 
			
		||||
        void SetScreenCapturePostPermission(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::GetScreenCapPostPermission service function
 | 
			
		||||
         * APT::GetScreenCapturePostPermission service function
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *      0 : Header Code[0x00560000]
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         *      2 : u8 The screenshot posting permission
 | 
			
		||||
         */
 | 
			
		||||
        void GetScreenCapPostPermission(Kernel::HLERequestContext& ctx);
 | 
			
		||||
        void GetScreenCapturePostPermission(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::CheckNew3DSApp service function
 | 
			
		||||
         * APT::WakeupApplication2 service function.
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *     1 : Buffer parameter size, (max is 0x1000)
 | 
			
		||||
         *     2 : Handle translation header (0x0)
 | 
			
		||||
         *     3 : Handle parameter
 | 
			
		||||
         *     4 : (Buffer parameter size << 14) | 2
 | 
			
		||||
         *     5 : Buffer parameter pointer
 | 
			
		||||
         * Outputs:
 | 
			
		||||
         *     0 : Return Header
 | 
			
		||||
         *     1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         */
 | 
			
		||||
        void WakeupApplication2(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::GetProgramId service function.
 | 
			
		||||
         *  Inputs:
 | 
			
		||||
         *     1 : Process ID translation header (0x20)
 | 
			
		||||
         *     2 : Process ID (filled in by kernel)
 | 
			
		||||
         * Outputs:
 | 
			
		||||
         *     0 : Return Header
 | 
			
		||||
         *     1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         *     2-3 : u64 Program ID
 | 
			
		||||
         */
 | 
			
		||||
        void GetProgramId(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::GetProgramInfo service function.
 | 
			
		||||
         * Inputs:
 | 
			
		||||
         *     1-2 : Title ID
 | 
			
		||||
         *     3 : Media Type
 | 
			
		||||
         *     4 : Padding
 | 
			
		||||
         * Outputs:
 | 
			
		||||
         *     1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         *     2 : Required app memory mode
 | 
			
		||||
         *     3 : Required app FIRM title ID low
 | 
			
		||||
         */
 | 
			
		||||
        void GetProgramInfo(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::Reboot service function.
 | 
			
		||||
         * Inputs:
 | 
			
		||||
         *     1-2 : Title ID
 | 
			
		||||
         *     3 : Media Type
 | 
			
		||||
         *     4 : Padding
 | 
			
		||||
         *     5 : Launch memory type
 | 
			
		||||
         *     6 : FIRM title ID low 32-bits
 | 
			
		||||
         * Outputs:
 | 
			
		||||
         *     1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         */
 | 
			
		||||
        void Reboot(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::HardwareResetAsync service function.
 | 
			
		||||
         * Outputs:
 | 
			
		||||
         *     1 : Result of function, 0 on success, otherwise error code
 | 
			
		||||
         */
 | 
			
		||||
        void HardwareResetAsync(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::GetTargetPlatform service function
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1: Result code, 0 on success, otherwise error code
 | 
			
		||||
         *      2: u8 output: 0 = Old3DS, 1 = New3DS.
 | 
			
		||||
| 
						 | 
				
			
			@ -849,7 +987,7 @@ public:
 | 
			
		|||
         *  Normally this NS state field is zero, however this state field is set to 1
 | 
			
		||||
         *  when APT:PrepareToStartApplication is used with flags bit8 is set.
 | 
			
		||||
         */
 | 
			
		||||
        void CheckNew3DSApp(Kernel::HLERequestContext& ctx);
 | 
			
		||||
        void GetTargetPlatform(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Wrapper for PTMSYSM:CheckNew3DS
 | 
			
		||||
| 
						 | 
				
			
			@ -861,12 +999,20 @@ public:
 | 
			
		|||
        void CheckNew3DS(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::Unknown0x0103 service function. Determines whether Smash 4 allows C-Stick
 | 
			
		||||
         * APT::GetApplicationRunningMode service function
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1: Result code, 0 on success otherwise error code
 | 
			
		||||
         *      2: u8 output: 2 = New3DS+valid/initialized (in Smash 4), 1 = Old3DS or invalid
 | 
			
		||||
         *      2: u8 output: 0 = No application, 1/3 = Old 3DS, 2/4 = New 3DS
 | 
			
		||||
         */
 | 
			
		||||
        void Unknown0x0103(Kernel::HLERequestContext& ctx);
 | 
			
		||||
        void GetApplicationRunningMode(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::IsStandardMemoryLayout service function
 | 
			
		||||
         *  Outputs:
 | 
			
		||||
         *      1: Result code, 0 on success otherwise error code
 | 
			
		||||
         *      2: bool output: Whether the system is in its standard memory layout.
 | 
			
		||||
         */
 | 
			
		||||
        void IsStandardMemoryLayout(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * APT::IsTitleAllowed service function
 | 
			
		||||
| 
						 | 
				
			
			@ -906,9 +1052,6 @@ private:
 | 
			
		|||
 | 
			
		||||
    u32 cpu_percent = 0; ///< CPU time available to the running application
 | 
			
		||||
 | 
			
		||||
    // APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode
 | 
			
		||||
    u8 unknown_ns_state_field = 0;
 | 
			
		||||
 | 
			
		||||
    std::array<u8, SysMenuArgSize> sys_menu_arg_buffer;
 | 
			
		||||
 | 
			
		||||
    ScreencapPostPermission screen_capture_post_permission =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,13 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0001, &APT_A::GetLockHandle, "GetLockHandle"},
 | 
			
		||||
        {0x0002, &APT_A::Initialize, "Initialize"},
 | 
			
		||||
        {0x0003, &APT_A::Enable, "Enable"},
 | 
			
		||||
        {0x0004, nullptr, "Finalize"},
 | 
			
		||||
        {0x0004, &APT_A::Finalize, "Finalize"},
 | 
			
		||||
        {0x0005, &APT_A::GetAppletManInfo, "GetAppletManInfo"},
 | 
			
		||||
        {0x0006, &APT_A::GetAppletInfo, "GetAppletInfo"},
 | 
			
		||||
        {0x0007, nullptr, "GetLastSignaledAppletId"},
 | 
			
		||||
        {0x0008, nullptr, "CountRegisteredApplet"},
 | 
			
		||||
        {0x0008, &APT_A::CountRegisteredApplet, "CountRegisteredApplet"},
 | 
			
		||||
        {0x0009, &APT_A::IsRegistered, "IsRegistered"},
 | 
			
		||||
        {0x000A, nullptr, "GetAttribute"},
 | 
			
		||||
        {0x000A, &APT_A::GetAttribute, "GetAttribute"},
 | 
			
		||||
        {0x000B, &APT_A::InquireNotification, "InquireNotification"},
 | 
			
		||||
        {0x000C, &APT_A::SendParameter, "SendParameter"},
 | 
			
		||||
        {0x000D, &APT_A::ReceiveParameter, "ReceiveParameter"},
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x001A, &APT_A::PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"},
 | 
			
		||||
        {0x001B, &APT_A::StartApplication, "StartApplication"},
 | 
			
		||||
        {0x001C, &APT_A::WakeupApplication, "WakeupApplication"},
 | 
			
		||||
        {0x001D, nullptr, "CancelApplication"},
 | 
			
		||||
        {0x001D, &APT_A::CancelApplication, "CancelApplication"},
 | 
			
		||||
        {0x001E, &APT_A::StartLibraryApplet, "StartLibraryApplet"},
 | 
			
		||||
        {0x001F, &APT_A::StartSystemApplet, "StartSystemApplet"},
 | 
			
		||||
        {0x0020, nullptr, "StartNewestHomeMenu"},
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0031, &APT_A::PrepareToDoApplicationJump, "PrepareToDoApplicationJump"},
 | 
			
		||||
        {0x0032, &APT_A::DoApplicationJump, "DoApplicationJump"},
 | 
			
		||||
        {0x0033, &APT_A::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
			
		||||
        {0x0034, nullptr, "SendDeliverArg"},
 | 
			
		||||
        {0x0034, &APT_A::SendDeliverArg, "SendDeliverArg"},
 | 
			
		||||
        {0x0035, &APT_A::ReceiveDeliverArg, "ReceiveDeliverArg"},
 | 
			
		||||
        {0x0036, &APT_A::LoadSysMenuArg, "LoadSysMenuArg"},
 | 
			
		||||
        {0x0037, &APT_A::StoreSysMenuArg, "StoreSysMenuArg"},
 | 
			
		||||
| 
						 | 
				
			
			@ -70,8 +70,8 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0039, nullptr, "PrepareToStartResidentApplet"},
 | 
			
		||||
        {0x003A, nullptr, "StartResidentApplet"},
 | 
			
		||||
        {0x003B, &APT_A::CancelLibraryApplet, "CancelLibraryApplet"},
 | 
			
		||||
        {0x003C, nullptr, "SendDspSleep"},
 | 
			
		||||
        {0x003D, nullptr, "SendDspWakeUp"},
 | 
			
		||||
        {0x003C, &APT_A::SendDspSleep, "SendDspSleep"},
 | 
			
		||||
        {0x003D, &APT_A::SendDspWakeUp, "SendDspWakeUp"},
 | 
			
		||||
        {0x003E, nullptr, "ReplySleepQuery"},
 | 
			
		||||
        {0x003F, nullptr, "ReplySleepNotificationComplete"},
 | 
			
		||||
        {0x0040, &APT_A::SendCaptureBufferInfo, "SendCaptureBufferInfo"},
 | 
			
		||||
| 
						 | 
				
			
			@ -82,26 +82,27 @@ APT_A::APT_A(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0045, &APT_A::GetWirelessRebootInfo, "GetWirelessRebootInfo"},
 | 
			
		||||
        {0x0046, &APT_A::Wrap, "Wrap"},
 | 
			
		||||
        {0x0047, &APT_A::Unwrap, "Unwrap"},
 | 
			
		||||
        {0x0048, nullptr, "GetProgramInfo"},
 | 
			
		||||
        {0x0049, nullptr, "Reboot"},
 | 
			
		||||
        {0x0048, &APT_A::GetProgramInfo, "GetProgramInfo"},
 | 
			
		||||
        {0x0049, &APT_A::Reboot, "Reboot"},
 | 
			
		||||
        {0x004A, &APT_A::GetCaptureInfo, "GetCaptureInfo"},
 | 
			
		||||
        {0x004B, &APT_A::AppletUtility, "AppletUtility"},
 | 
			
		||||
        {0x004C, nullptr, "SetFatalErrDispMode"},
 | 
			
		||||
        {0x004D, nullptr, "GetAppletProgramInfo"},
 | 
			
		||||
        {0x004E, nullptr, "HardwareResetAsync"},
 | 
			
		||||
        {0x004E, &APT_A::HardwareResetAsync, "HardwareResetAsync"},
 | 
			
		||||
        {0x004F, &APT_A::SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
 | 
			
		||||
        {0x0050, &APT_A::GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
 | 
			
		||||
        {0x0051, &APT_A::GetStartupArgument, "GetStartupArgument"},
 | 
			
		||||
        {0x0052, nullptr, "Wrap1"},
 | 
			
		||||
        {0x0053, nullptr, "Unwrap1"},
 | 
			
		||||
        {0x0055, &APT_A::SetScreenCapPostPermission, "SetScreenCapPostPermission"},
 | 
			
		||||
        {0x0056, &APT_A::GetScreenCapPostPermission, "GetScreenCapPostPermission"},
 | 
			
		||||
        {0x0057, nullptr, "WakeupApplication2"},
 | 
			
		||||
        {0x0058, nullptr, "GetProgramID"},
 | 
			
		||||
        {0x0101, &APT_A::CheckNew3DSApp, "CheckNew3DSApp"},
 | 
			
		||||
        {0x0054, &APT_A::Unknown54, "Unknown54"},
 | 
			
		||||
        {0x0055, &APT_A::SetScreenCapturePostPermission, "SetScreenCapturePostPermission"},
 | 
			
		||||
        {0x0056, &APT_A::GetScreenCapturePostPermission, "GetScreenCapturePostPermission"},
 | 
			
		||||
        {0x0057, &APT_A::WakeupApplication2, "WakeupApplication2"},
 | 
			
		||||
        {0x0058, &APT_A::GetProgramId, "GetProgramId"},
 | 
			
		||||
        {0x0101, &APT_A::GetTargetPlatform, "GetTargetPlatform"},
 | 
			
		||||
        {0x0102, &APT_A::CheckNew3DS, "CheckNew3DS"},
 | 
			
		||||
        {0x0103, &APT_A::Unknown0x0103, "Unknown0x0103"},
 | 
			
		||||
        {0x0104, nullptr, "IsStandardMemoryLayout"},
 | 
			
		||||
        {0x0103, &APT_A::GetApplicationRunningMode, "GetApplicationRunningMode"},
 | 
			
		||||
        {0x0104, &APT_A::IsStandardMemoryLayout, "IsStandardMemoryLayout"},
 | 
			
		||||
        {0x0105, &APT_A::IsTitleAllowed, "IsTitleAllowed"},
 | 
			
		||||
        // clang-format on
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,13 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0001, &APT_S::GetLockHandle, "GetLockHandle"},
 | 
			
		||||
        {0x0002, &APT_S::Initialize, "Initialize"},
 | 
			
		||||
        {0x0003, &APT_S::Enable, "Enable"},
 | 
			
		||||
        {0x0004, nullptr, "Finalize"},
 | 
			
		||||
        {0x0004, &APT_S::Finalize, "Finalize"},
 | 
			
		||||
        {0x0005, &APT_S::GetAppletManInfo, "GetAppletManInfo"},
 | 
			
		||||
        {0x0006, &APT_S::GetAppletInfo, "GetAppletInfo"},
 | 
			
		||||
        {0x0007, nullptr, "GetLastSignaledAppletId"},
 | 
			
		||||
        {0x0008, nullptr, "CountRegisteredApplet"},
 | 
			
		||||
        {0x0008, &APT_S::CountRegisteredApplet, "CountRegisteredApplet"},
 | 
			
		||||
        {0x0009, &APT_S::IsRegistered, "IsRegistered"},
 | 
			
		||||
        {0x000A, nullptr, "GetAttribute"},
 | 
			
		||||
        {0x000A, &APT_S::GetAttribute, "GetAttribute"},
 | 
			
		||||
        {0x000B, &APT_S::InquireNotification, "InquireNotification"},
 | 
			
		||||
        {0x000C, &APT_S::SendParameter, "SendParameter"},
 | 
			
		||||
        {0x000D, &APT_S::ReceiveParameter, "ReceiveParameter"},
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x001A, &APT_S::PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"},
 | 
			
		||||
        {0x001B, &APT_S::StartApplication, "StartApplication"},
 | 
			
		||||
        {0x001C, &APT_S::WakeupApplication, "WakeupApplication"},
 | 
			
		||||
        {0x001D, nullptr, "CancelApplication"},
 | 
			
		||||
        {0x001D, &APT_S::CancelApplication, "CancelApplication"},
 | 
			
		||||
        {0x001E, &APT_S::StartLibraryApplet, "StartLibraryApplet"},
 | 
			
		||||
        {0x001F, &APT_S::StartSystemApplet, "StartSystemApplet"},
 | 
			
		||||
        {0x0020, nullptr, "StartNewestHomeMenu"},
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0031, &APT_S::PrepareToDoApplicationJump, "PrepareToDoApplicationJump"},
 | 
			
		||||
        {0x0032, &APT_S::DoApplicationJump, "DoApplicationJump"},
 | 
			
		||||
        {0x0033, &APT_S::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
			
		||||
        {0x0034, nullptr, "SendDeliverArg"},
 | 
			
		||||
        {0x0034, &APT_S::SendDeliverArg, "SendDeliverArg"},
 | 
			
		||||
        {0x0035, &APT_S::ReceiveDeliverArg, "ReceiveDeliverArg"},
 | 
			
		||||
        {0x0036, &APT_S::LoadSysMenuArg, "LoadSysMenuArg"},
 | 
			
		||||
        {0x0037, &APT_S::StoreSysMenuArg, "StoreSysMenuArg"},
 | 
			
		||||
| 
						 | 
				
			
			@ -70,8 +70,8 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0039, nullptr, "PrepareToStartResidentApplet"},
 | 
			
		||||
        {0x003A, nullptr, "StartResidentApplet"},
 | 
			
		||||
        {0x003B, &APT_S::CancelLibraryApplet, "CancelLibraryApplet"},
 | 
			
		||||
        {0x003C, nullptr, "SendDspSleep"},
 | 
			
		||||
        {0x003D, nullptr, "SendDspWakeUp"},
 | 
			
		||||
        {0x003C, &APT_S::SendDspSleep, "SendDspSleep"},
 | 
			
		||||
        {0x003D, &APT_S::SendDspWakeUp, "SendDspWakeUp"},
 | 
			
		||||
        {0x003E, nullptr, "ReplySleepQuery"},
 | 
			
		||||
        {0x003F, nullptr, "ReplySleepNotificationComplete"},
 | 
			
		||||
        {0x0040, &APT_S::SendCaptureBufferInfo, "SendCaptureBufferInfo"},
 | 
			
		||||
| 
						 | 
				
			
			@ -82,26 +82,27 @@ APT_S::APT_S(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0045, &APT_S::GetWirelessRebootInfo, "GetWirelessRebootInfo"},
 | 
			
		||||
        {0x0046, &APT_S::Wrap, "Wrap"},
 | 
			
		||||
        {0x0047, &APT_S::Unwrap, "Unwrap"},
 | 
			
		||||
        {0x0048, nullptr, "GetProgramInfo"},
 | 
			
		||||
        {0x0049, nullptr, "Reboot"},
 | 
			
		||||
        {0x0048, &APT_S::GetProgramInfo, "GetProgramInfo"},
 | 
			
		||||
        {0x0049, &APT_S::Reboot, "Reboot"},
 | 
			
		||||
        {0x004A, &APT_S::GetCaptureInfo, "GetCaptureInfo"},
 | 
			
		||||
        {0x004B, &APT_S::AppletUtility, "AppletUtility"},
 | 
			
		||||
        {0x004C, nullptr, "SetFatalErrDispMode"},
 | 
			
		||||
        {0x004D, nullptr, "GetAppletProgramInfo"},
 | 
			
		||||
        {0x004E, nullptr, "HardwareResetAsync"},
 | 
			
		||||
        {0x004E, &APT_S::HardwareResetAsync, "HardwareResetAsync"},
 | 
			
		||||
        {0x004F, &APT_S::SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
 | 
			
		||||
        {0x0050, &APT_S::GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
 | 
			
		||||
        {0x0051, &APT_S::GetStartupArgument, "GetStartupArgument"},
 | 
			
		||||
        {0x0052, nullptr, "Wrap1"},
 | 
			
		||||
        {0x0053, nullptr, "Unwrap1"},
 | 
			
		||||
        {0x0055, &APT_S::SetScreenCapPostPermission, "SetScreenCapPostPermission"},
 | 
			
		||||
        {0x0056, &APT_S::GetScreenCapPostPermission, "GetScreenCapPostPermission"},
 | 
			
		||||
        {0x0057, nullptr, "WakeupApplication2"},
 | 
			
		||||
        {0x0058, nullptr, "GetProgramID"},
 | 
			
		||||
        {0x0101, &APT_S::CheckNew3DSApp, "CheckNew3DSApp"},
 | 
			
		||||
        {0x0054, &APT_S::Unknown54, "Unknown54"},
 | 
			
		||||
        {0x0055, &APT_S::SetScreenCapturePostPermission, "SetScreenCapturePostPermission"},
 | 
			
		||||
        {0x0056, &APT_S::GetScreenCapturePostPermission, "GetScreenCapturePostPermission"},
 | 
			
		||||
        {0x0057, &APT_S::WakeupApplication2, "WakeupApplication2"},
 | 
			
		||||
        {0x0058, &APT_S::GetProgramId, "GetProgramId"},
 | 
			
		||||
        {0x0101, &APT_S::GetTargetPlatform, "GetTargetPlatform"},
 | 
			
		||||
        {0x0102, &APT_S::CheckNew3DS, "CheckNew3DS"},
 | 
			
		||||
        {0x0103, &APT_S::Unknown0x0103, "Unknown0x0103"},
 | 
			
		||||
        {0x0104, nullptr, "IsStandardMemoryLayout"},
 | 
			
		||||
        {0x0103, &APT_S::GetApplicationRunningMode, "GetApplicationRunningMode"},
 | 
			
		||||
        {0x0104, &APT_S::IsStandardMemoryLayout, "IsStandardMemoryLayout"},
 | 
			
		||||
        {0x0105, &APT_S::IsTitleAllowed, "IsTitleAllowed"},
 | 
			
		||||
        // clang-format on
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,13 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0001, &APT_U::GetLockHandle, "GetLockHandle"},
 | 
			
		||||
        {0x0002, &APT_U::Initialize, "Initialize"},
 | 
			
		||||
        {0x0003, &APT_U::Enable, "Enable"},
 | 
			
		||||
        {0x0004, nullptr, "Finalize"},
 | 
			
		||||
        {0x0004, &APT_U::Finalize, "Finalize"},
 | 
			
		||||
        {0x0005, &APT_U::GetAppletManInfo, "GetAppletManInfo"},
 | 
			
		||||
        {0x0006, &APT_U::GetAppletInfo, "GetAppletInfo"},
 | 
			
		||||
        {0x0007, nullptr, "GetLastSignaledAppletId"},
 | 
			
		||||
        {0x0008, nullptr, "CountRegisteredApplet"},
 | 
			
		||||
        {0x0008, &APT_U::CountRegisteredApplet, "CountRegisteredApplet"},
 | 
			
		||||
        {0x0009, &APT_U::IsRegistered, "IsRegistered"},
 | 
			
		||||
        {0x000A, nullptr, "GetAttribute"},
 | 
			
		||||
        {0x000A, &APT_U::GetAttribute, "GetAttribute"},
 | 
			
		||||
        {0x000B, &APT_U::InquireNotification, "InquireNotification"},
 | 
			
		||||
        {0x000C, &APT_U::SendParameter, "SendParameter"},
 | 
			
		||||
        {0x000D, &APT_U::ReceiveParameter, "ReceiveParameter"},
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x001A, &APT_U::PrepareToStartNewestHomeMenu, "PrepareToStartNewestHomeMenu"},
 | 
			
		||||
        {0x001B, &APT_U::StartApplication, "StartApplication"},
 | 
			
		||||
        {0x001C, &APT_U::WakeupApplication, "WakeupApplication"},
 | 
			
		||||
        {0x001D, nullptr, "CancelApplication"},
 | 
			
		||||
        {0x001D, &APT_U::CancelApplication, "CancelApplication"},
 | 
			
		||||
        {0x001E, &APT_U::StartLibraryApplet, "StartLibraryApplet"},
 | 
			
		||||
        {0x001F, &APT_U::StartSystemApplet, "StartSystemApplet"},
 | 
			
		||||
        {0x0020, nullptr, "StartNewestHomeMenu"},
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0031, &APT_U::PrepareToDoApplicationJump, "PrepareToDoApplicationJump"},
 | 
			
		||||
        {0x0032, &APT_U::DoApplicationJump, "DoApplicationJump"},
 | 
			
		||||
        {0x0033, &APT_U::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"},
 | 
			
		||||
        {0x0034, nullptr, "SendDeliverArg"},
 | 
			
		||||
        {0x0034, &APT_U::SendDeliverArg, "SendDeliverArg"},
 | 
			
		||||
        {0x0035, &APT_U::ReceiveDeliverArg, "ReceiveDeliverArg"},
 | 
			
		||||
        {0x0036, &APT_U::LoadSysMenuArg, "LoadSysMenuArg"},
 | 
			
		||||
        {0x0037, &APT_U::StoreSysMenuArg, "StoreSysMenuArg"},
 | 
			
		||||
| 
						 | 
				
			
			@ -70,8 +70,8 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0039, nullptr, "PrepareToStartResidentApplet"},
 | 
			
		||||
        {0x003A, nullptr, "StartResidentApplet"},
 | 
			
		||||
        {0x003B, &APT_U::CancelLibraryApplet, "CancelLibraryApplet"},
 | 
			
		||||
        {0x003C, nullptr, "SendDspSleep"},
 | 
			
		||||
        {0x003D, nullptr, "SendDspWakeUp"},
 | 
			
		||||
        {0x003C, &APT_U::SendDspSleep, "SendDspSleep"},
 | 
			
		||||
        {0x003D, &APT_U::SendDspWakeUp, "SendDspWakeUp"},
 | 
			
		||||
        {0x003E, nullptr, "ReplySleepQuery"},
 | 
			
		||||
        {0x003F, nullptr, "ReplySleepNotificationComplete"},
 | 
			
		||||
        {0x0040, &APT_U::SendCaptureBufferInfo, "SendCaptureBufferInfo"},
 | 
			
		||||
| 
						 | 
				
			
			@ -82,26 +82,27 @@ APT_U::APT_U(std::shared_ptr<Module> apt)
 | 
			
		|||
        {0x0045, &APT_U::GetWirelessRebootInfo, "GetWirelessRebootInfo"},
 | 
			
		||||
        {0x0046, &APT_U::Wrap, "Wrap"},
 | 
			
		||||
        {0x0047, &APT_U::Unwrap, "Unwrap"},
 | 
			
		||||
        {0x0048, nullptr, "GetProgramInfo"},
 | 
			
		||||
        {0x0049, nullptr, "Reboot"},
 | 
			
		||||
        {0x0048, &APT_U::GetProgramInfo, "GetProgramInfo"},
 | 
			
		||||
        {0x0049, &APT_U::Reboot, "Reboot"},
 | 
			
		||||
        {0x004A, &APT_U::GetCaptureInfo, "GetCaptureInfo"},
 | 
			
		||||
        {0x004B, &APT_U::AppletUtility, "AppletUtility"},
 | 
			
		||||
        {0x004C, nullptr, "SetFatalErrDispMode"},
 | 
			
		||||
        {0x004D, nullptr, "GetAppletProgramInfo"},
 | 
			
		||||
        {0x004E, nullptr, "HardwareResetAsync"},
 | 
			
		||||
        {0x004E, &APT_U::HardwareResetAsync, "HardwareResetAsync"},
 | 
			
		||||
        {0x004F, &APT_U::SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
 | 
			
		||||
        {0x0050, &APT_U::GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
 | 
			
		||||
        {0x0051, &APT_U::GetStartupArgument, "GetStartupArgument"},
 | 
			
		||||
        {0x0052, nullptr, "Wrap1"},
 | 
			
		||||
        {0x0053, nullptr, "Unwrap1"},
 | 
			
		||||
        {0x0055, &APT_U::SetScreenCapPostPermission, "SetScreenCapPostPermission"},
 | 
			
		||||
        {0x0056, &APT_U::GetScreenCapPostPermission, "GetScreenCapPostPermission"},
 | 
			
		||||
        {0x0057, nullptr, "WakeupApplication2"},
 | 
			
		||||
        {0x0058, nullptr, "GetProgramID"},
 | 
			
		||||
        {0x0101, &APT_U::CheckNew3DSApp, "CheckNew3DSApp"},
 | 
			
		||||
        {0x0054, &APT_U::Unknown54, "Unknown54"},
 | 
			
		||||
        {0x0055, &APT_U::SetScreenCapturePostPermission, "SetScreenCapturePostPermission"},
 | 
			
		||||
        {0x0056, &APT_U::GetScreenCapturePostPermission, "GetScreenCapturePostPermission"},
 | 
			
		||||
        {0x0057, &APT_U::WakeupApplication2, "WakeupApplication2"},
 | 
			
		||||
        {0x0058, &APT_U::GetProgramId, "GetProgramId"},
 | 
			
		||||
        {0x0101, &APT_U::GetTargetPlatform, "GetTargetPlatform"},
 | 
			
		||||
        {0x0102, &APT_U::CheckNew3DS, "CheckNew3DS"},
 | 
			
		||||
        {0x0103, &APT_U::Unknown0x0103, "Unknown0x0103"},
 | 
			
		||||
        {0x0104, nullptr, "IsStandardMemoryLayout"},
 | 
			
		||||
        {0x0103, &APT_U::GetApplicationRunningMode, "GetApplicationRunningMode"},
 | 
			
		||||
        {0x0104, &APT_U::IsStandardMemoryLayout, "IsStandardMemoryLayout"},
 | 
			
		||||
        {0x0105, &APT_U::IsTitleAllowed, "IsTitleAllowed"},
 | 
			
		||||
        // clang-format on
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,5 +8,6 @@ namespace Service::APT::ErrCodes {
 | 
			
		|||
enum {
 | 
			
		||||
    ParameterPresent = 2,
 | 
			
		||||
    InvalidAppletSlot = 4,
 | 
			
		||||
    AppNotRunning = 11,
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::APT::ErrCodes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,4 +29,17 @@ std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title
 | 
			
		|||
    return process;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id) {
 | 
			
		||||
    auto new_path = AM::GetTitleContentPath(media_type, title_id);
 | 
			
		||||
    if (new_path.empty() || !FileUtil::Exists(new_path)) {
 | 
			
		||||
        // TODO: This can happen if the requested title is not installed. Need a way to find
 | 
			
		||||
        // non-installed titles in the game list.
 | 
			
		||||
        LOG_CRITICAL(Service_APT,
 | 
			
		||||
                     "Failed to find title '{}' to jump to, resetting current title instead.",
 | 
			
		||||
                     new_path);
 | 
			
		||||
        new_path.clear();
 | 
			
		||||
    }
 | 
			
		||||
    system.RequestReset(new_path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::NS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,4 +18,7 @@ namespace Service::NS {
 | 
			
		|||
/// Loads and launches the title identified by title_id in the specified media type.
 | 
			
		||||
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id);
 | 
			
		||||
 | 
			
		||||
/// Reboots the system to the specified title.
 | 
			
		||||
void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id);
 | 
			
		||||
 | 
			
		||||
} // namespace Service::NS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue