mirror of
https://github.com/XorTroll/uLaunch
synced 2024-11-22 11:53:06 +00:00
Some cleanup, small fixes, ECS working fine now
This commit is contained in:
parent
f086264fb5
commit
aa492d8fe3
36 changed files with 697 additions and 697 deletions
|
@ -1,4 +1,4 @@
|
||||||
<img width="200" src="LibraryAppletQMenu/RomFs/LogoLarge.png">
|
<img width="200" src="LibraryAppletDaemon/RomFs/LogoLarge.png">
|
||||||
|
|
||||||
> Custom, open-source replacement/reimplementation for Nintendo Switch's HOME menu (qlaunch), extending it with amazing, homebrew-oriented functionality!
|
> Custom, open-source replacement/reimplementation for Nintendo Switch's HOME menu (qlaunch), extending it with amazing, homebrew-oriented functionality!
|
||||||
|
|
||||||
|
|
2
TODO.md
2
TODO.md
|
@ -1,6 +1,6 @@
|
||||||
# uLaunch's TODO list
|
# uLaunch's TODO list
|
||||||
|
|
||||||
- Improve QDaemons's IPC with two services, one only for QMenu and the other one for any process to interact with uLaunch:
|
- Improve Daemons's IPC with two services, one only for Daemon and the other one for any process to interact with uLaunch:
|
||||||
|
|
||||||
- Easy way to detect whether uLaunch is present
|
- Easy way to detect whether uLaunch is present
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e5c501e5b66fbeeb57cbc03856582ad470084aca
|
Subproject commit b83ddf8157e7aef37159aaff9e0b40b137339504
|
|
@ -2,57 +2,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include <ul_Include.hpp>
|
#include <ul_Include.hpp>
|
||||||
|
#include <am/am_Application.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace ecs
|
namespace ecs
|
||||||
{
|
{
|
||||||
NX_CONSTEXPR AppletId DetectAppletIdByProgramId(u64 program_id)
|
|
||||||
{
|
|
||||||
switch(program_id)
|
|
||||||
{
|
|
||||||
case 0x0100000000001001:
|
|
||||||
return AppletId_auth;
|
|
||||||
case 0x0100000000001002:
|
|
||||||
return AppletId_cabinet;
|
|
||||||
case 0x0100000000001003:
|
|
||||||
return AppletId_controller;
|
|
||||||
case 0x0100000000001004:
|
|
||||||
return AppletId_dataErase;
|
|
||||||
case 0x0100000000001005:
|
|
||||||
return AppletId_error;
|
|
||||||
case 0x0100000000001006:
|
|
||||||
return AppletId_netConnect;
|
|
||||||
case 0x0100000000001007:
|
|
||||||
return AppletId_playerSelect;
|
|
||||||
case 0x0100000000001008:
|
|
||||||
return AppletId_swkbd;
|
|
||||||
case 0x0100000000001009:
|
|
||||||
return AppletId_miiEdit;
|
|
||||||
case 0x010000000000100A:
|
|
||||||
return AppletId_web;
|
|
||||||
case 0x010000000000100B:
|
|
||||||
return AppletId_shop;
|
|
||||||
case 0x010000000000100D:
|
|
||||||
return AppletId_photoViewer;
|
|
||||||
case 0x010000000000100E:
|
|
||||||
return AppletId_set;
|
|
||||||
case 0x010000000000100F:
|
|
||||||
return AppletId_offlineWeb;
|
|
||||||
case 0x0100000000001010:
|
|
||||||
return AppletId_loginShare;
|
|
||||||
case 0x0100000000001011:
|
|
||||||
return AppletId_wifiWebAuth;
|
|
||||||
case 0x0100000000001013:
|
|
||||||
return AppletId_myPage;
|
|
||||||
}
|
|
||||||
return (AppletId)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Initialize();
|
Result Initialize();
|
||||||
void Exit();
|
void Exit();
|
||||||
Result RegisterExternalContent(u64 program_id, std::string exefs_path);
|
Result RegisterExternalContent(u64 program_id, std::string exefs_path);
|
||||||
Result LaunchApplet(u64 program_id, u32 la_version, void *args, size_t args_size);
|
Result LaunchApplet(u64 program_id, u32 la_version, void *args, size_t args_size);
|
||||||
Result LaunchApplication(u64 program_id, void *args, size_t args_size, AccountUid uid);
|
|
||||||
Result LaunchSystemProcess(u64 program_id, std::string argv_str);
|
Result LaunchSystemProcess(u64 program_id, std::string argv_str);
|
||||||
|
|
||||||
inline Result RegisterLaunchAsApplet(u64 program_id, u32 la_version, std::string exefs_path, void *args, size_t args_size)
|
inline Result RegisterLaunchAsApplet(u64 program_id, u32 la_version, std::string exefs_path, void *args, size_t args_size)
|
||||||
|
@ -65,7 +23,7 @@ namespace ecs
|
||||||
inline Result RegisterLaunchAsApplication(u64 program_id, std::string exefs_path, void *args, size_t args_size, AccountUid uid)
|
inline Result RegisterLaunchAsApplication(u64 program_id, std::string exefs_path, void *args, size_t args_size, AccountUid uid)
|
||||||
{
|
{
|
||||||
auto rc = RegisterExternalContent(program_id, exefs_path);
|
auto rc = RegisterExternalContent(program_id, exefs_path);
|
||||||
if(R_SUCCEEDED(rc)) rc = LaunchApplication(program_id, args, args_size, uid);
|
if(R_SUCCEEDED(rc)) rc = am::ApplicationStart(program_id, false, uid, args, args_size);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
#include <am/am_Application.hpp>
|
#include <am/am_Application.hpp>
|
||||||
#include <am/am_LibraryApplet.hpp>
|
#include <am/am_LibraryApplet.hpp>
|
||||||
#include <am/am_HomeMenu.hpp>
|
#include <am/am_HomeMenu.hpp>
|
||||||
#include <am/am_QCommunications.hpp>
|
#include <am/am_DaemonMenuInteraction.hpp>
|
||||||
#include <util/util_Convert.hpp>
|
#include <util/util_Convert.hpp>
|
||||||
#include <cfg/cfg_Config.hpp>
|
#include <cfg/cfg_Config.hpp>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
u32 __nx_applet_type = AppletType_SystemApplet;
|
u32 __nx_applet_type = AppletType_SystemApplet;
|
||||||
|
TimeServiceType __nx_time_service_type = TimeServiceType_System;
|
||||||
#if UL_DEV
|
#if UL_DEV
|
||||||
size_t __nx_heap_size = 0x3000000; // Dev builds use 48MB (still lower than official qlaunch) for debug console
|
size_t __nx_heap_size = 0x3000000; // Dev builds use 48MB (still lower than official qlaunch) for debug console
|
||||||
#else
|
#else
|
||||||
|
@ -35,11 +36,12 @@ namespace ams
|
||||||
|
|
||||||
AccountUid selected_uid = {};
|
AccountUid selected_uid = {};
|
||||||
hb::HbTargetParams hblaunch_flag = {};
|
hb::HbTargetParams hblaunch_flag = {};
|
||||||
hb::HbTargetParams hbapplaunch_copy = {};
|
|
||||||
hb::HbTargetParams hbapplaunch_flag = {};
|
hb::HbTargetParams hbapplaunch_flag = {};
|
||||||
|
hb::HbTargetParams hbapplaunch_flag_temp = {};
|
||||||
u64 titlelaunch_flag = 0;
|
u64 titlelaunch_flag = 0;
|
||||||
WebCommonConfig webapplet_flag = {};
|
WebCommonConfig webapplet_flag = {};
|
||||||
bool album_flag = false;
|
bool album_flag = false;
|
||||||
|
bool app_opened_hb = false;
|
||||||
u8 *usbbuf = nullptr;
|
u8 *usbbuf = nullptr;
|
||||||
cfg::Config config = {};
|
cfg::Config config = {};
|
||||||
Thread ipc_thr;
|
Thread ipc_thr;
|
||||||
|
@ -49,22 +51,22 @@ Thread usb_thr;
|
||||||
bool debug_menu = false;
|
bool debug_menu = false;
|
||||||
|
|
||||||
ams::os::Mutex latestqlock;
|
ams::os::Mutex latestqlock;
|
||||||
am::QMenuMessage latestqmenumsg = am::QMenuMessage::Invalid;
|
am::MenuMessage latestqmenumsg = am::MenuMessage::Invalid;
|
||||||
|
|
||||||
am::QDaemonStatus CreateStatus()
|
am::DaemonStatus CreateStatus()
|
||||||
{
|
{
|
||||||
am::QDaemonStatus status = {};
|
am::DaemonStatus status = {};
|
||||||
memcpy(&status.selected_user, &selected_uid, sizeof(selected_uid));
|
memcpy(&status.selected_user, &selected_uid, sizeof(selected_uid));
|
||||||
|
|
||||||
cfg::TitleType tmptype = cfg::TitleType::Invalid;
|
cfg::TitleType tmptype = cfg::TitleType::Invalid;
|
||||||
if(am::ApplicationIsActive())
|
if(am::ApplicationIsActive())
|
||||||
{
|
{
|
||||||
tmptype = cfg::TitleType::Installed;
|
tmptype = cfg::TitleType::Installed;
|
||||||
if(os::IsFlogTitle(am::ApplicationGetId())) tmptype = cfg::TitleType::Homebrew;
|
if(app_opened_hb) tmptype = cfg::TitleType::Homebrew;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tmptype == cfg::TitleType::Installed) status.app_id = am::ApplicationGetId();
|
if(tmptype == cfg::TitleType::Installed) status.app_id = am::ApplicationGetId();
|
||||||
else if(tmptype == cfg::TitleType::Homebrew) status.params = hbapplaunch_copy;
|
else if(tmptype == cfg::TitleType::Homebrew) memcpy(&status.params, &hbapplaunch_flag_temp, sizeof(hbapplaunch_flag_temp));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -74,20 +76,20 @@ void HandleSleep()
|
||||||
appletStartSleepSequence(true);
|
appletStartSleepSequence(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LaunchMenu(am::QMenuStartMode stmode, am::QDaemonStatus status)
|
Result LaunchMenu(am::MenuStartMode stmode, am::DaemonStatus status)
|
||||||
{
|
{
|
||||||
if(debug_menu) return 0;
|
if(debug_menu) return 0;
|
||||||
return ecs::RegisterLaunchAsApplet(0x010000000000100B, (u32)stmode, "/ulaunch/bin/uMenu/", &status, sizeof(status));
|
return ecs::RegisterLaunchAsApplet(config.menu_program_id, (u32)stmode, "/ulaunch/bin/uMenu/", &status, sizeof(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleHomeButton()
|
void HandleHomeButton()
|
||||||
{
|
{
|
||||||
bool used_to_reopen_menu = false;
|
bool used_to_reopen_menu = false;
|
||||||
if(am::LibraryAppletIsActive() && !am::LibraryAppletIsQMenu())
|
if(am::LibraryAppletIsActive() && !am::LibraryAppletIsMenu())
|
||||||
{
|
{
|
||||||
am::LibraryAppletTerminate();
|
am::LibraryAppletTerminate();
|
||||||
auto status = CreateStatus();
|
auto status = CreateStatus();
|
||||||
UL_R_TRY(LaunchMenu(am::QMenuStartMode::Menu, status));
|
UL_R_TRY(LaunchMenu(am::MenuStartMode::Menu, status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(am::ApplicationIsActive())
|
if(am::ApplicationIsActive())
|
||||||
|
@ -96,14 +98,14 @@ void HandleHomeButton()
|
||||||
{
|
{
|
||||||
am::HomeMenuSetForeground();
|
am::HomeMenuSetForeground();
|
||||||
auto status = CreateStatus();
|
auto status = CreateStatus();
|
||||||
UL_R_TRY(LaunchMenu(am::QMenuStartMode::MenuApplicationSuspended, status));
|
UL_R_TRY(LaunchMenu(am::MenuStartMode::MenuApplicationSuspended, status));
|
||||||
used_to_reopen_menu = true;
|
used_to_reopen_menu = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(am::LibraryAppletIsQMenu() && !used_to_reopen_menu)
|
if(am::LibraryAppletIsMenu() && !used_to_reopen_menu)
|
||||||
{
|
{
|
||||||
std::scoped_lock _lock(latestqlock);
|
std::scoped_lock _lock(latestqlock);
|
||||||
latestqmenumsg = am::QMenuMessage::HomeRequest;
|
latestqmenumsg = am::MenuMessage::HomeRequest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,162 +187,165 @@ void HandleAppletMessage()
|
||||||
|
|
||||||
void HandleMenuMessage()
|
void HandleMenuMessage()
|
||||||
{
|
{
|
||||||
if(am::LibraryAppletIsQMenu())
|
if(am::LibraryAppletIsMenu())
|
||||||
{
|
{
|
||||||
am::QDaemonCommandReader reader;
|
am::DaemonCommandReader reader;
|
||||||
if(reader)
|
if(reader)
|
||||||
{
|
{
|
||||||
switch(reader.GetMessage())
|
switch(reader.GetMessage())
|
||||||
{
|
{
|
||||||
case am::QDaemonMessage::SetSelectedUser:
|
case am::DaemonMessage::SetSelectedUser:
|
||||||
{
|
{
|
||||||
selected_uid = reader.Read<AccountUid>();
|
selected_uid = reader.Read<AccountUid>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::LaunchApplication:
|
case am::DaemonMessage::LaunchApplication:
|
||||||
{
|
{
|
||||||
auto app_id = reader.Read<u64>();
|
auto app_id = reader.Read<u64>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
if(am::ApplicationIsActive())
|
if(am::ApplicationIsActive())
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, ApplicationActive));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, ApplicationActive));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else if(!accountUidIsValid(&selected_uid))
|
else if(!accountUidIsValid(&selected_uid))
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, InvalidSelectedUser));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, InvalidSelectedUser));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else if(titlelaunch_flag > 0)
|
else if(titlelaunch_flag > 0)
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, AlreadyQueued));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, AlreadyQueued));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
titlelaunch_flag = app_id;
|
titlelaunch_flag = app_id;
|
||||||
am::QDaemonCommandResultWriter res(0);
|
am::DaemonCommandResultWriter res(0);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::ResumeApplication:
|
case am::DaemonMessage::ResumeApplication:
|
||||||
{
|
{
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
if(!am::ApplicationIsActive())
|
if(!am::ApplicationIsActive())
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, ApplicationNotActive));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, ApplicationNotActive));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
am::ApplicationSetForeground();
|
am::ApplicationSetForeground();
|
||||||
am::QDaemonCommandResultWriter res(0);
|
am::DaemonCommandResultWriter res(0);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::TerminateApplication:
|
case am::DaemonMessage::TerminateApplication:
|
||||||
{
|
{
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
am::ApplicationTerminate();
|
am::ApplicationTerminate();
|
||||||
|
app_opened_hb = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::LaunchHomebrewLibApplet:
|
case am::DaemonMessage::LaunchHomebrewLibraryApplet:
|
||||||
{
|
{
|
||||||
hblaunch_flag = reader.Read<hb::HbTargetParams>();
|
hblaunch_flag = reader.Read<hb::HbTargetParams>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::LaunchHomebrewApplication:
|
case am::DaemonMessage::LaunchHomebrewApplication:
|
||||||
{
|
{
|
||||||
|
auto app_id = reader.Read<u64>();
|
||||||
auto ipt = reader.Read<hb::HbTargetParams>();
|
auto ipt = reader.Read<hb::HbTargetParams>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
if(am::ApplicationIsActive())
|
if(am::ApplicationIsActive())
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, ApplicationActive));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, ApplicationActive));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else if(!accountUidIsValid(&selected_uid))
|
else if(!accountUidIsValid(&selected_uid))
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, InvalidSelectedUser));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, InvalidSelectedUser));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else if(titlelaunch_flag > 0)
|
else if(titlelaunch_flag > 0)
|
||||||
{
|
{
|
||||||
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, AlreadyQueued));
|
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, AlreadyQueued));
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hbapplaunch_copy = ipt;
|
memcpy(&hbapplaunch_flag, &ipt, sizeof(ipt));
|
||||||
hbapplaunch_flag = hbapplaunch_copy;
|
memcpy(&hbapplaunch_flag_temp, &ipt, sizeof(ipt));
|
||||||
am::QDaemonCommandResultWriter res(0);
|
titlelaunch_flag = app_id;
|
||||||
|
am::DaemonCommandResultWriter res(0);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::OpenWebPage:
|
case am::DaemonMessage::OpenWebPage:
|
||||||
{
|
{
|
||||||
webapplet_flag = reader.Read<WebCommonConfig>();
|
webapplet_flag = reader.Read<WebCommonConfig>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::GetSelectedUser:
|
case am::DaemonMessage::GetSelectedUser:
|
||||||
{
|
{
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
am::QDaemonCommandResultWriter res(0);
|
am::DaemonCommandResultWriter res(0);
|
||||||
res.Write<AccountUid>(selected_uid);
|
res.Write<AccountUid>(selected_uid);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::UserHasPassword:
|
case am::DaemonMessage::UserHasPassword:
|
||||||
{
|
{
|
||||||
auto uid = reader.Read<AccountUid>();
|
auto uid = reader.Read<AccountUid>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
auto [rc, pass] = db::AccessPassword(uid);
|
auto [rc, pass] = db::AccessPassword(uid);
|
||||||
|
|
||||||
am::QDaemonCommandResultWriter res(rc);
|
am::DaemonCommandResultWriter res(rc);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::TryLogUser:
|
case am::DaemonMessage::TryLogUser:
|
||||||
{
|
{
|
||||||
auto pass = reader.Read<db::PassBlock>();
|
auto pass = reader.Read<db::PassBlock>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
auto rc = db::TryLogUser(pass);
|
auto rc = db::TryLogUser(pass);
|
||||||
|
|
||||||
am::QDaemonCommandResultWriter res(rc);
|
am::DaemonCommandResultWriter res(rc);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::RegisterUserPassword:
|
case am::DaemonMessage::RegisterUserPassword:
|
||||||
{
|
{
|
||||||
auto pass = reader.Read<db::PassBlock>();
|
auto pass = reader.Read<db::PassBlock>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
auto rc = db::RegisterUserPassword(pass);
|
auto rc = db::RegisterUserPassword(pass);
|
||||||
|
|
||||||
am::QDaemonCommandResultWriter res(rc);
|
am::DaemonCommandResultWriter res(rc);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::ChangeUserPassword:
|
case am::DaemonMessage::ChangeUserPassword:
|
||||||
{
|
{
|
||||||
auto pass = reader.Read<db::PassBlock>();
|
auto pass = reader.Read<db::PassBlock>();
|
||||||
auto newpass = reader.Read<db::PassBlock>();
|
auto newpass = reader.Read<db::PassBlock>();
|
||||||
|
@ -353,12 +358,12 @@ void HandleMenuMessage()
|
||||||
if(R_SUCCEEDED(rc)) rc = db::RegisterUserPassword(newpass);
|
if(R_SUCCEEDED(rc)) rc = db::RegisterUserPassword(newpass);
|
||||||
}
|
}
|
||||||
|
|
||||||
am::QDaemonCommandResultWriter res(rc);
|
am::DaemonCommandResultWriter res(rc);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::RemoveUserPassword:
|
case am::DaemonMessage::RemoveUserPassword:
|
||||||
{
|
{
|
||||||
auto pass = reader.Read<db::PassBlock>();
|
auto pass = reader.Read<db::PassBlock>();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
@ -369,12 +374,12 @@ void HandleMenuMessage()
|
||||||
rc = db::RemoveUserPassword(pass.uid);
|
rc = db::RemoveUserPassword(pass.uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
am::QDaemonCommandResultWriter res(rc);
|
am::DaemonCommandResultWriter res(rc);
|
||||||
res.FinishWrite();
|
res.FinishWrite();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case am::QDaemonMessage::OpenAlbum:
|
case am::DaemonMessage::OpenAlbum:
|
||||||
{
|
{
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
album_flag = true;
|
album_flag = true;
|
||||||
|
@ -400,15 +405,15 @@ namespace
|
||||||
constexpr size_t MaxServers = 2;
|
constexpr size_t MaxServers = 2;
|
||||||
constexpr size_t MaxSessions = 2;
|
constexpr size_t MaxSessions = 2;
|
||||||
|
|
||||||
constexpr ams::sm::ServiceName PrivateServiceName = ams::sm::ServiceName::Encode(AM_QDAEMON_SERVICE_NAME);
|
constexpr ams::sm::ServiceName PrivateServiceName = ams::sm::ServiceName::Encode(AM_DAEMON_PRIVATE_SERVICE_NAME);
|
||||||
ams::sf::hipc::ServerManager<MaxServers, ServerOptions, MaxSessions> private_service_manager;
|
ams::sf::hipc::ServerManager<MaxServers, ServerOptions, MaxSessions> private_service_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace qdaemon
|
namespace daemn
|
||||||
{
|
{
|
||||||
void IPCManagerThread(void *arg)
|
void IPCManagerThread(void *arg)
|
||||||
{
|
{
|
||||||
private_service_manager.RegisterServer<ipc::IDaemonService>(PrivateServiceName, MaxSessions);
|
UL_R_TRY(private_service_manager.RegisterServer<ipc::IDaemonService>(PrivateServiceName, MaxSessions).GetValue());
|
||||||
private_service_manager.LoopProcess();
|
private_service_manager.LoopProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +440,7 @@ namespace qdaemon
|
||||||
{
|
{
|
||||||
if(!am::LibraryAppletIsActive())
|
if(!am::LibraryAppletIsActive())
|
||||||
{
|
{
|
||||||
am::WebAppletStart(&webapplet_flag);
|
UL_R_TRY(am::WebAppletStart(&webapplet_flag));
|
||||||
|
|
||||||
sth_done = true;
|
sth_done = true;
|
||||||
memset(&webapplet_flag, 0, sizeof(webapplet_flag));
|
memset(&webapplet_flag, 0, sizeof(webapplet_flag));
|
||||||
|
@ -446,7 +451,7 @@ namespace qdaemon
|
||||||
if(!am::LibraryAppletIsActive())
|
if(!am::LibraryAppletIsActive())
|
||||||
{
|
{
|
||||||
u8 albumflag = 2;
|
u8 albumflag = 2;
|
||||||
am::LibraryAppletStart(AppletId_photoViewer, 0x10000, &albumflag, sizeof(albumflag));
|
UL_R_TRY(am::LibraryAppletStart(AppletId_photoViewer, 0x10000, &albumflag, sizeof(albumflag)));
|
||||||
|
|
||||||
sth_done = true;
|
sth_done = true;
|
||||||
album_flag = false;
|
album_flag = false;
|
||||||
|
@ -456,18 +461,21 @@ namespace qdaemon
|
||||||
{
|
{
|
||||||
if(!am::LibraryAppletIsActive())
|
if(!am::LibraryAppletIsActive())
|
||||||
{
|
{
|
||||||
am::ApplicationStart(titlelaunch_flag, false, selected_uid);
|
if(strlen(hbapplaunch_flag.nro_path))
|
||||||
sth_done = true;
|
{
|
||||||
titlelaunch_flag = 0;
|
auto params = hb::HbTargetParams::Create(hbapplaunch_flag.nro_path, hbapplaunch_flag.nro_argv, false);
|
||||||
}
|
UL_R_TRY(ecs::RegisterLaunchAsApplication(titlelaunch_flag, "/ulaunch/bin/uHbTarget/app/", ¶ms, sizeof(params), selected_uid));
|
||||||
}
|
sth_done = true;
|
||||||
if(strlen(hbapplaunch_flag.nro_path))
|
app_opened_hb = true;
|
||||||
{
|
titlelaunch_flag = 0;
|
||||||
if(!am::LibraryAppletIsActive())
|
hbapplaunch_flag.nro_path[0] = '\0';
|
||||||
{
|
}
|
||||||
am::ApplicationStart(OS_FLOG_APP_ID, true, selected_uid, &hbapplaunch_flag, sizeof(hbapplaunch_flag));
|
else
|
||||||
sth_done = true;
|
{
|
||||||
hbapplaunch_flag.nro_path[0] = '\0';
|
UL_R_TRY(am::ApplicationStart(titlelaunch_flag, false, selected_uid));
|
||||||
|
sth_done = true;
|
||||||
|
titlelaunch_flag = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(strlen(hblaunch_flag.nro_path))
|
if(strlen(hblaunch_flag.nro_path))
|
||||||
|
@ -475,36 +483,29 @@ namespace qdaemon
|
||||||
if(!am::LibraryAppletIsActive())
|
if(!am::LibraryAppletIsActive())
|
||||||
{
|
{
|
||||||
auto params = hb::HbTargetParams::Create(hblaunch_flag.nro_path, hblaunch_flag.nro_argv, false);
|
auto params = hb::HbTargetParams::Create(hblaunch_flag.nro_path, hblaunch_flag.nro_argv, false);
|
||||||
auto rc = ecs::RegisterLaunchAsApplet(0x0100000000001003, 0, "/ulaunch/bin/uHbTarget/applet/", ¶ms, sizeof(params));
|
UL_R_TRY(ecs::RegisterLaunchAsApplet(config.homebrew_applet_program_id, 0, "/ulaunch/bin/uHbTarget/applet/", ¶ms, sizeof(params)));
|
||||||
sth_done = true;
|
sth_done = true;
|
||||||
hblaunch_flag.nro_path[0] = '\0';
|
hblaunch_flag.nro_path[0] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!am::LibraryAppletIsActive())
|
if(!am::LibraryAppletIsActive())
|
||||||
{
|
{
|
||||||
switch(am::LibraryAppletGetId())
|
auto cur_id = am::LibraryAppletGetId();
|
||||||
|
if((cur_id == AppletId_web) || (cur_id == AppletId_photoViewer) || (cur_id == config.homebrew_applet_program_id))
|
||||||
{
|
{
|
||||||
case am::QHbTargetAppletId:
|
auto status = CreateStatus();
|
||||||
case AppletId_web:
|
UL_R_TRY(LaunchMenu(am::MenuStartMode::Menu, status));
|
||||||
case AppletId_photoViewer:
|
sth_done = true;
|
||||||
{
|
|
||||||
auto status = CreateStatus();
|
|
||||||
UL_R_TRY(LaunchMenu(am::QMenuStartMode::Menu, status));
|
|
||||||
sth_done = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!sth_done && !debug_menu)
|
if(!sth_done && !debug_menu)
|
||||||
{
|
{
|
||||||
// If nothing was done, but nothing is active... An application or applet might have crashed, terminated, failed to launch...
|
// If nothing was done, but nothing is active... An application or applet might have crashed, terminated, failed to launch...
|
||||||
// No matter what is it, we reopen QMenu in launch-error mode.
|
// No matter what is it, we reopen Menu in launch-error mode.
|
||||||
if(!am::ApplicationIsActive() && !am::LibraryAppletIsActive())
|
if(!am::ApplicationIsActive() && !am::LibraryAppletIsActive())
|
||||||
{
|
{
|
||||||
auto status = CreateStatus();
|
auto status = CreateStatus();
|
||||||
UL_R_TRY(LaunchMenu(am::QMenuStartMode::MenuLaunchFailure, status));
|
UL_R_TRY(LaunchMenu(am::MenuStartMode::MenuLaunchFailure, status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,6 +548,7 @@ namespace qdaemon
|
||||||
fs::CreateDirectory(UL_BASE_SD_DIR "/lang");
|
fs::CreateDirectory(UL_BASE_SD_DIR "/lang");
|
||||||
|
|
||||||
config = cfg::EnsureConfig();
|
config = cfg::EnsureConfig();
|
||||||
|
am::LibraryAppletSetMenuAppletId(am::LibraryAppletGetAppletIdForProgramId(config.menu_program_id));
|
||||||
|
|
||||||
if(config.viewer_usb_enabled)
|
if(config.viewer_usb_enabled)
|
||||||
{
|
{
|
||||||
|
@ -624,24 +626,24 @@ namespace qdaemon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QDaemon handles basic qlaunch functionality and serves as a back-end for uLaunch, communicating with QMenu front-end when neccessary.
|
// Daemon handles basic qlaunch functionality and serves as a back-end for uLaunch, communicating with Menu front-end when neccessary.
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
qdaemon::Initialize();
|
daemn::Initialize();
|
||||||
|
|
||||||
// Cache everything on startup
|
// Cache everything on startup
|
||||||
cfg::CacheEverything();
|
cfg::CacheEverything();
|
||||||
|
|
||||||
auto status = CreateStatus();
|
auto status = CreateStatus();
|
||||||
UL_R_TRY(LaunchMenu(am::QMenuStartMode::StartupScreen, status))
|
UL_R_TRY(LaunchMenu(am::MenuStartMode::StartupScreen, status))
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
qdaemon::LoopUpdate();
|
daemn::LoopUpdate();
|
||||||
svcSleepThread(10'000'000);
|
svcSleepThread(10'000'000);
|
||||||
}
|
}
|
||||||
|
|
||||||
qdaemon::Exit();
|
daemn::Exit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
#include <am/am_Application.hpp>
|
#include <am/am_Application.hpp>
|
||||||
#include <am/am_LibraryApplet.hpp>
|
#include <am/am_LibraryApplet.hpp>
|
||||||
#include <am/am_HomeMenu.hpp>
|
#include <am/am_HomeMenu.hpp>
|
||||||
#include <am/am_QCommunications.hpp>
|
#include <am/am_DaemonMenuInteraction.hpp>
|
||||||
|
|
||||||
namespace ecs
|
namespace ecs
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ namespace ecs
|
||||||
ams::sf::hipc::ServerManager<MaxServers, ServerOptions> manager_instance;
|
ams::sf::hipc::ServerManager<MaxServers, ServerOptions> manager_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ManagerLoopHandler(void *arg)
|
static void ECSManagerThread(void *arg)
|
||||||
{
|
{
|
||||||
manager_instance.LoopProcess();
|
manager_instance.LoopProcess();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace ecs
|
||||||
initialized = R_SUCCEEDED(rc);
|
initialized = R_SUCCEEDED(rc);
|
||||||
if(initialized)
|
if(initialized)
|
||||||
{
|
{
|
||||||
R_TRY(threadCreate(&manager_process_thread, &ManagerLoopHandler, nullptr, nullptr, 0x8000, 0x2b, -2));
|
R_TRY(threadCreate(&manager_process_thread, &ECSManagerThread, nullptr, nullptr, 0x8000, 0x2b, -2));
|
||||||
R_TRY(threadStart(&manager_process_thread));
|
R_TRY(threadStart(&manager_process_thread));
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -87,15 +87,10 @@ namespace ecs
|
||||||
Result LaunchApplet(u64 program_id, u32 la_version, void *args, size_t args_size)
|
Result LaunchApplet(u64 program_id, u32 la_version, void *args, size_t args_size)
|
||||||
{
|
{
|
||||||
Result rc = 0xdead;
|
Result rc = 0xdead;
|
||||||
auto appletid = DetectAppletIdByProgramId(program_id);
|
auto appletid = am::LibraryAppletGetAppletIdForProgramId(program_id);
|
||||||
if(appletid != 0) rc = am::LibraryAppletStart(appletid, la_version, args, args_size);
|
if(appletid != 0) rc = am::LibraryAppletStart(appletid, la_version, args, args_size);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LaunchApplication(u64 program_id, void *args, size_t args_size, AccountUid uid)
|
|
||||||
{
|
|
||||||
return am::ApplicationStart(program_id, false, uid, args, args_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result LaunchSystemProcess(u64 program_id, std::string argv_str)
|
Result LaunchSystemProcess(u64 program_id, std::string argv_str)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include <ipc/ipc_IDaemonService.hpp>
|
#include <ipc/ipc_IDaemonService.hpp>
|
||||||
#include <am/am_QCommunications.hpp>
|
#include <am/am_DaemonMenuInteraction.hpp>
|
||||||
|
|
||||||
extern ams::os::Mutex latestqlock;
|
extern ams::os::Mutex latestqlock;
|
||||||
extern am::QMenuMessage latestqmenumsg;
|
extern am::DaemonMessage latestqmenumsg;
|
||||||
|
|
||||||
namespace ipc
|
namespace ipc
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,6 @@ namespace ipc
|
||||||
{
|
{
|
||||||
std::scoped_lock _lock(latestqlock);
|
std::scoped_lock _lock(latestqlock);
|
||||||
msg.SetValue((u32)latestqmenumsg);
|
msg.SetValue((u32)latestqmenumsg);
|
||||||
latestqmenumsg = am::QMenuMessage::Invalid;
|
latestqmenumsg = am::DaemonMessage::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,11 +17,10 @@ namespace am
|
||||||
static_assert(sizeof(ApplicationSelectedUserArgument) == 0x400, "ApplicationSelectedUserArgument must be 0x400!");
|
static_assert(sizeof(ApplicationSelectedUserArgument) == 0x400, "ApplicationSelectedUserArgument must be 0x400!");
|
||||||
|
|
||||||
static constexpr u32 SelectedUserMagic = 0xC79497CA;
|
static constexpr u32 SelectedUserMagic = 0xC79497CA;
|
||||||
static constexpr u64 QHbTargetSystemApplicationId = OS_FLOG_APP_ID;
|
|
||||||
|
|
||||||
bool ApplicationIsActive();
|
bool ApplicationIsActive();
|
||||||
void ApplicationTerminate();
|
void ApplicationTerminate();
|
||||||
Result ApplicationStart(u64 app_id, bool system, AccountUid user_id, void *data = NULL, size_t size = 0);
|
Result ApplicationStart(u64 app_id, bool system, AccountUid user_id, void *data = nullptr, size_t size = 0);
|
||||||
bool ApplicationHasForeground();
|
bool ApplicationHasForeground();
|
||||||
Result ApplicationSetForeground();
|
Result ApplicationSetForeground();
|
||||||
Result ApplicationSend(void *data, size_t size, AppletLaunchParameterKind kind = AppletLaunchParameterKind_UserChannel);
|
Result ApplicationSend(void *data, size_t size, AppletLaunchParameterKind kind = AppletLaunchParameterKind_UserChannel);
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
#include <ul_Include.hpp>
|
#include <ul_Include.hpp>
|
||||||
#include <hb/hb_Target.hpp>
|
#include <hb/hb_Target.hpp>
|
||||||
|
|
||||||
|
#define AM_DAEMON_PRIVATE_SERVICE_NAME "qdmnsrv"
|
||||||
|
#define AM_DAEMON_PUBLIC_SERVICE_NAME "ulaunch"
|
||||||
|
|
||||||
namespace am
|
namespace am
|
||||||
{
|
{
|
||||||
enum class QMenuStartMode
|
enum class MenuStartMode
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
StartupScreen,
|
StartupScreen,
|
||||||
|
@ -14,20 +17,20 @@ namespace am
|
||||||
MenuLaunchFailure
|
MenuLaunchFailure
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class QMenuMessage
|
enum class MenuMessage
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
HomeRequest
|
HomeRequest
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class QDaemonMessage
|
enum class DaemonMessage
|
||||||
{
|
{
|
||||||
Invalid,
|
Invalid,
|
||||||
SetSelectedUser,
|
SetSelectedUser,
|
||||||
LaunchApplication,
|
LaunchApplication,
|
||||||
ResumeApplication,
|
ResumeApplication,
|
||||||
TerminateApplication,
|
TerminateApplication,
|
||||||
LaunchHomebrewLibApplet,
|
LaunchHomebrewLibraryApplet,
|
||||||
LaunchHomebrewApplication,
|
LaunchHomebrewApplication,
|
||||||
OpenWebPage,
|
OpenWebPage,
|
||||||
GetSelectedUser,
|
GetSelectedUser,
|
||||||
|
@ -39,36 +42,29 @@ namespace am
|
||||||
OpenAlbum,
|
OpenAlbum,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QDaemonStatus
|
struct DaemonStatus
|
||||||
{
|
{
|
||||||
AccountUid selected_user;
|
AccountUid selected_user;
|
||||||
hb::HbTargetParams params; // Set if homebrew (via flog takeover) is suspended
|
hb::HbTargetParams params; // Set if homebrew (via flog takeover) is suspended
|
||||||
u64 app_id; // Set if any title (other than flog) is suspended
|
u64 app_id; // Set if any title (other than flog) is suspended
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AM_QDAEMON_SERVICE_NAME "qdmnsrv"
|
ResultWith<MenuStartMode> Menu_ProcessInput();
|
||||||
|
|
||||||
Result QDaemon_LaunchQMenu(QMenuStartMode mode, QDaemonStatus status);
|
Result Menu_InitializeDaemonService();
|
||||||
// Result QDaemon_LaunchQHbTarget(hb::HbTargetParams input);
|
ResultWith<MenuMessage> Menu_GetLatestMenuMessage();
|
||||||
|
bool MenuIsHomePressed();
|
||||||
|
void Menu_FinalizeDaemonService();
|
||||||
|
|
||||||
Result QLibraryAppletReadStorage(void *data, size_t size);
|
Result Daemon_MenuWriteImpl(void *data, size_t size, bool wait);
|
||||||
Result QApplicationReadStorage(void *data, size_t size);
|
Result Daemon_MenuReadImpl(void *data, size_t size, bool wait);
|
||||||
ResultWith<QMenuStartMode> QMenu_ProcessInput();
|
|
||||||
|
|
||||||
Result QMenu_InitializeDaemonService();
|
Result Menu_DaemonWriteImpl(void *data, size_t size, bool wait);
|
||||||
ResultWith<QMenuMessage> QMenu_GetLatestQMenuMessage();
|
Result Menu_DaemonReadImpl(void *data, size_t size, bool wait);
|
||||||
bool QMenuIsHomePressed();
|
|
||||||
void QMenu_FinalizeDaemonService();
|
|
||||||
|
|
||||||
Result QDaemon_QMenuWriteImpl(void *data, size_t size, bool wait);
|
typedef Result(*DMCommandRWFunction)(void*, size_t, bool);
|
||||||
Result QDaemon_QMenuReadImpl(void *data, size_t size, bool wait);
|
|
||||||
|
|
||||||
Result QMenu_QDaemonWriteImpl(void *data, size_t size, bool wait);
|
struct DMCommandCommonHeader
|
||||||
Result QMenu_QDaemonReadImpl(void *data, size_t size, bool wait);
|
|
||||||
|
|
||||||
typedef Result(*QCommandRWFunction)(void*, size_t, bool);
|
|
||||||
|
|
||||||
struct QCommandCommonHeader
|
|
||||||
{
|
{
|
||||||
u32 magic;
|
u32 magic;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
@ -77,18 +73,18 @@ namespace am
|
||||||
static constexpr u32 Magic = 0x434D4151;
|
static constexpr u32 Magic = 0x434D4151;
|
||||||
static constexpr size_t BlockSize = 0x4000;
|
static constexpr size_t BlockSize = 0x4000;
|
||||||
|
|
||||||
template<QCommandRWFunction WriteFn>
|
template<DMCommandRWFunction WriteFn>
|
||||||
class QCommandWriter
|
class DMCommandWriter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
QCommandCommonHeader request;
|
DMCommandCommonHeader request;
|
||||||
u8 *data_block;
|
u8 *data_block;
|
||||||
size_t data_pos;
|
size_t data_pos;
|
||||||
Result inner_rc;
|
Result inner_rc;
|
||||||
bool write_done;
|
bool write_done;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QCommandWriter(u32 value)
|
DMCommandWriter(u32 value)
|
||||||
{
|
{
|
||||||
write_done = false;
|
write_done = false;
|
||||||
request.magic = Magic;
|
request.magic = Magic;
|
||||||
|
@ -98,7 +94,7 @@ namespace am
|
||||||
inner_rc = WriteFn(&request, sizeof(request), false);
|
inner_rc = WriteFn(&request, sizeof(request), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
~QCommandWriter()
|
~DMCommandWriter()
|
||||||
{
|
{
|
||||||
FinishWrite();
|
FinishWrite();
|
||||||
}
|
}
|
||||||
|
@ -131,11 +127,11 @@ namespace am
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<QCommandRWFunction ReadFn>
|
template<DMCommandRWFunction ReadFn>
|
||||||
class QCommandReader
|
class DMCommandReader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
QCommandCommonHeader response;
|
DMCommandCommonHeader response;
|
||||||
u8 *data_block;
|
u8 *data_block;
|
||||||
size_t data_pos;
|
size_t data_pos;
|
||||||
Result inner_rc;
|
Result inner_rc;
|
||||||
|
@ -143,17 +139,17 @@ namespace am
|
||||||
bool fn_wait;
|
bool fn_wait;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QCommandReader(bool wait = false)
|
DMCommandReader(bool wait = false)
|
||||||
{
|
{
|
||||||
fn_wait = wait;
|
fn_wait = wait;
|
||||||
read_done = false;
|
read_done = false;
|
||||||
data_pos = 0;
|
data_pos = 0;
|
||||||
data_block = new u8[BlockSize]();
|
data_block = new u8[BlockSize]();
|
||||||
inner_rc = ReadFn(&response, sizeof(QCommandCommonHeader), fn_wait);
|
inner_rc = ReadFn(&response, sizeof(DMCommandCommonHeader), fn_wait);
|
||||||
if(R_SUCCEEDED(inner_rc)) inner_rc = ReadFn(data_block, BlockSize, fn_wait);
|
if(R_SUCCEEDED(inner_rc)) inner_rc = ReadFn(data_block, BlockSize, fn_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
~QCommandReader()
|
~DMCommandReader()
|
||||||
{
|
{
|
||||||
FinishRead();
|
FinishRead();
|
||||||
}
|
}
|
||||||
|
@ -191,27 +187,27 @@ namespace am
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QDaemonCommandReader : public QCommandReader<QDaemon_QMenuReadImpl>
|
class DaemonCommandReader : public DMCommandReader<Daemon_MenuReadImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QDaemonMessage GetMessage()
|
DaemonMessage GetMessage()
|
||||||
{
|
{
|
||||||
return (QDaemonMessage)GetValue();
|
return (DaemonMessage)GetValue();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QDaemonCommandWriter : public QCommandWriter<QDaemon_QMenuWriteImpl>
|
class DaemonCommandWriter : public DMCommandWriter<Daemon_MenuWriteImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QDaemonCommandWriter(QMenuMessage msg) : QCommandWriter((u32)msg)
|
DaemonCommandWriter(MenuMessage msg) : DMCommandWriter((u32)msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QDaemonCommandResultReader : public QCommandReader<QDaemon_QMenuReadImpl>
|
class DaemonCommandResultReader : public DMCommandReader<Daemon_MenuReadImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QDaemonCommandResultReader() : QCommandReader(true)
|
DaemonCommandResultReader() : DMCommandReader(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,35 +217,35 @@ namespace am
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QDaemonCommandResultWriter : public QCommandWriter<QDaemon_QMenuWriteImpl>
|
class DaemonCommandResultWriter : public DMCommandWriter<Daemon_MenuWriteImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QDaemonCommandResultWriter(Result rc) : QCommandWriter(rc)
|
DaemonCommandResultWriter(Result rc) : DMCommandWriter(rc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMenuCommandReader : public QCommandReader<QMenu_QDaemonReadImpl>
|
class MenuCommandReader : public DMCommandReader<Menu_DaemonReadImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QMenuMessage GetMessage()
|
MenuMessage GetMessage()
|
||||||
{
|
{
|
||||||
return (QMenuMessage)GetValue();
|
return (MenuMessage)GetValue();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMenuCommandWriter : public QCommandWriter<QMenu_QDaemonWriteImpl>
|
class MenuCommandWriter : public DMCommandWriter<Menu_DaemonWriteImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QMenuCommandWriter(QDaemonMessage msg) : QCommandWriter((u32)msg)
|
MenuCommandWriter(DaemonMessage msg) : DMCommandWriter((u32)msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMenuCommandResultReader : public QCommandReader<QMenu_QDaemonReadImpl>
|
class MenuCommandResultReader : public DMCommandReader<Menu_DaemonReadImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QMenuCommandResultReader() : QCommandReader(true)
|
MenuCommandResultReader() : DMCommandReader(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,10 +255,10 @@ namespace am
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMenuCommandResultWriter : public QCommandWriter<QMenu_QDaemonWriteImpl>
|
class MenuCommandResultWriter : public DMCommandWriter<Menu_DaemonWriteImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QMenuCommandResultWriter(Result rc) : QCommandWriter(rc)
|
MenuCommandResultWriter(Result rc) : DMCommandWriter(rc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <ul_Include.hpp>
|
#include <ul_Include.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace am
|
namespace am
|
||||||
{
|
{
|
||||||
|
@ -33,29 +34,32 @@ namespace am
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibraryAppletIsActive();
|
bool LibraryAppletIsActive();
|
||||||
bool LibraryAppletIsQMenu();
|
void LibraryAppletSetMenuAppletId(AppletId id);
|
||||||
|
bool LibraryAppletIsMenu();
|
||||||
void LibraryAppletTerminate();
|
void LibraryAppletTerminate();
|
||||||
Result LibraryAppletStart(AppletId id, u32 la_version, void *in_data, size_t in_size);
|
Result LibraryAppletStart(AppletId id, u32 la_version, void *in_data, size_t in_size);
|
||||||
Result LibraryAppletSend(void *data, size_t size);
|
Result LibraryAppletSend(void *data, size_t size);
|
||||||
Result LibraryAppletRead(void *data, size_t size);
|
Result LibraryAppletRead(void *data, size_t size);
|
||||||
Result WebAppletStart(WebCommonConfig *web);
|
Result WebAppletStart(WebCommonConfig *web);
|
||||||
Result LibraryAppletQMenuLaunchWith(AppletId id, u32 la_version, std::function<void(AppletHolder*)> on_prepare, std::function<void(AppletHolder*)> on_finish, std::function<bool()> on_wait);
|
Result LibraryAppletDaemonLaunchWith(AppletId id, u32 la_version, std::function<void(AppletHolder*)> on_prepare, std::function<void(AppletHolder*)> on_finish, std::function<bool()> on_wait);
|
||||||
|
|
||||||
inline Result LibraryAppletQMenuLaunchWithSimple(AppletId id, u32 la_version, void *in_data, size_t in_size, void *out_data, size_t out_size, std::function<bool()> on_wait)
|
inline Result LibraryAppletDaemonLaunchWithSimple(AppletId id, u32 la_version, void *in_data, size_t in_size, void *out_data, size_t out_size, std::function<bool()> on_wait)
|
||||||
{
|
{
|
||||||
return LibraryAppletQMenuLaunchWith(id, la_version,
|
return LibraryAppletDaemonLaunchWith(id, la_version,
|
||||||
[&](AppletHolder *h)
|
[&](AppletHolder *h)
|
||||||
{
|
{
|
||||||
if(in_size > 0) libappletPushInData(h, in_data, in_size);
|
if(in_size > 0) libappletPushInData(h, in_data, in_size);
|
||||||
},
|
},
|
||||||
[&](AppletHolder *h)
|
[&](AppletHolder *h)
|
||||||
{
|
{
|
||||||
if(out_size > 0) libappletPopOutData(h, out_data, out_size, NULL);
|
if(out_size > 0) libappletPopOutData(h, out_data, out_size, nullptr);
|
||||||
}, on_wait);
|
}, on_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 LibraryAppletGetProgramIdForAppletId(AppletId id);
|
||||||
|
AppletId LibraryAppletGetAppletIdForProgramId(u64 id);
|
||||||
|
|
||||||
AppletId LibraryAppletGetId();
|
AppletId LibraryAppletGetId();
|
||||||
|
|
||||||
static constexpr AppletId QMenuAppletId = AppletId_shop;
|
static constexpr AppletId InvalidAppletId = (AppletId)0;
|
||||||
static constexpr AppletId QHbTargetAppletId = AppletId_auth;
|
|
||||||
}
|
}
|
|
@ -69,14 +69,25 @@ namespace cfg
|
||||||
std::string icon_path;
|
std::string icon_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Take over eShop by default
|
||||||
|
static constexpr u64 DefaultMenuProgramId = 0x010000000000100B;
|
||||||
|
|
||||||
|
// Take over parental controls applet by default
|
||||||
|
static constexpr u64 DefaultHomebrewAppletProgramId = 0x0100000000001001;
|
||||||
|
|
||||||
struct Config
|
struct Config
|
||||||
{
|
{
|
||||||
std::string theme_name;
|
std::string theme_name;
|
||||||
bool system_title_override_enabled;
|
bool system_title_override_enabled;
|
||||||
bool viewer_usb_enabled;
|
bool viewer_usb_enabled;
|
||||||
|
u64 menu_program_id;
|
||||||
|
u64 homebrew_applet_program_id;
|
||||||
|
u64 homebrew_title_application_id;
|
||||||
|
|
||||||
JSON main_lang;
|
JSON main_lang;
|
||||||
JSON default_lang;
|
JSON default_lang;
|
||||||
|
|
||||||
|
Config() : system_title_override_enabled(false), viewer_usb_enabled(false), menu_program_id(DefaultMenuProgramId), homebrew_applet_program_id(DefaultHomebrewAppletProgramId), homebrew_title_application_id(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr u32 CurrentThemeFormatVersion = 1;
|
static constexpr u32 CurrentThemeFormatVersion = 1;
|
||||||
|
@ -86,35 +97,35 @@ namespace cfg
|
||||||
#define CFG_CONFIG_JSON UL_BASE_SD_DIR "/config.json"
|
#define CFG_CONFIG_JSON UL_BASE_SD_DIR "/config.json"
|
||||||
|
|
||||||
TitleList LoadTitleList();
|
TitleList LoadTitleList();
|
||||||
std::vector<TitleRecord> QueryAllHomebrew(std::string base = "sdmc:/switch");
|
std::vector<TitleRecord> QueryAllHomebrew(const std::string &base = "sdmc:/switch");
|
||||||
void CacheEverything(std::string hb_base_path = "sdmc:/switch");
|
void CacheEverything(const std::string &hb_base_path = "sdmc:/switch");
|
||||||
std::string GetRecordIconPath(TitleRecord record);
|
std::string GetRecordIconPath(TitleRecord record);
|
||||||
RecordInformation GetRecordInformation(TitleRecord record);
|
RecordInformation GetRecordInformation(TitleRecord record);
|
||||||
|
|
||||||
Theme LoadTheme(std::string base_name);
|
Theme LoadTheme(const std::string &base_name);
|
||||||
std::vector<Theme> LoadThemes();
|
std::vector<Theme> LoadThemes();
|
||||||
std::string GetAssetByTheme(Theme &base, std::string resource_base);
|
std::string GetAssetByTheme(const Theme &base, const std::string &resource_base);
|
||||||
|
|
||||||
inline bool ThemeIsDefault(Theme &base)
|
inline bool ThemeIsDefault(const Theme &base)
|
||||||
{
|
{
|
||||||
return base.base_name.empty();
|
return base.base_name.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetLanguageJSONPath(std::string lang);
|
std::string GetLanguageJSONPath(const std::string &lang);
|
||||||
std::string GetLanguageString(JSON &lang, JSON &def, std::string name);
|
std::string GetLanguageString(const JSON &lang, const JSON &def, const std::string &name);
|
||||||
|
|
||||||
Config CreateNewAndLoadConfig();
|
Config CreateNewAndLoadConfig();
|
||||||
Config LoadConfig();
|
Config LoadConfig();
|
||||||
Config EnsureConfig();
|
Config EnsureConfig();
|
||||||
void SaveConfig(Config &cfg);
|
void SaveConfig(const Config &cfg);
|
||||||
|
|
||||||
void SaveRecord(TitleRecord &record);
|
void SaveRecord(TitleRecord &record);
|
||||||
void RemoveRecord(TitleRecord &record);
|
void RemoveRecord(TitleRecord &record);
|
||||||
bool MoveRecordTo(TitleList &list, TitleRecord record, std::string folder);
|
bool MoveRecordTo(TitleList &list, TitleRecord record, const std::string &folder);
|
||||||
TitleFolder &FindFolderByName(TitleList &list, std::string name);
|
TitleFolder &FindFolderByName(TitleList &list, const std::string &name);
|
||||||
void RenameFolder(TitleList &list, std::string old_name, std::string new_name);
|
void RenameFolder(TitleList &list, const std::string &old_name, const std::string &new_name);
|
||||||
bool ExistsRecord(TitleList &list, TitleRecord record);
|
bool ExistsRecord(TitleList &list, TitleRecord record);
|
||||||
|
|
||||||
std::string GetTitleCacheIconPath(u64 app_id);
|
std::string GetTitleCacheIconPath(u64 app_id);
|
||||||
std::string GetNROCacheIconPath(std::string path);
|
std::string GetNROCacheIconPath(const std::string &path);
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@ namespace db
|
||||||
void Unmount();
|
void Unmount();
|
||||||
void Commit();
|
void Commit();
|
||||||
|
|
||||||
ResultWith<PassBlock> PackPassword(AccountUid uid, std::string pass);
|
ResultWith<PassBlock> PackPassword(AccountUid uid, const std::string &pass);
|
||||||
ResultWith<PassBlock> AccessPassword(AccountUid user_id);
|
ResultWith<PassBlock> AccessPassword(AccountUid user_id);
|
||||||
std::string GetUserPasswordFilePath(AccountUid user_id);
|
std::string GetUserPasswordFilePath(AccountUid user_id);
|
||||||
Result RegisterUserPassword(PassBlock password);
|
Result RegisterUserPassword(PassBlock password);
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
|
|
||||||
namespace fs
|
namespace fs
|
||||||
{
|
{
|
||||||
bool ExistsFile(std::string path);
|
bool ExistsFile(const std::string &path);
|
||||||
bool ExistsDirectory(std::string path);
|
bool ExistsDirectory(const std::string &path);
|
||||||
|
|
||||||
void CreateDirectory(std::string path);
|
void CreateDirectory(const std::string &path);
|
||||||
void CreateFile(std::string path);
|
void CreateFile(const std::string &path);
|
||||||
void CreateConcatenationFile(std::string path);
|
void CreateConcatenationFile(const std::string &path);
|
||||||
|
|
||||||
void DeleteDirectory(std::string path);
|
void DeleteDirectory(const std::string &path);
|
||||||
void DeleteFile(std::string path);
|
void DeleteFile(const std::string &path);
|
||||||
|
|
||||||
inline bool WriteFile(std::string path, void *data, size_t size, bool overwrite)
|
inline bool WriteFile(const std::string &path, void *data, size_t size, bool overwrite)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(path.c_str(), overwrite ? "wb" : "ab+");
|
FILE *f = fopen(path.c_str(), overwrite ? "wb" : "ab+");
|
||||||
if(f)
|
if(f)
|
||||||
|
@ -26,7 +26,7 @@ namespace fs
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ReadFile(std::string path, void *data, size_t size)
|
inline bool ReadFile(const std::string &path, void *data, size_t size)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(path.c_str(), "rb");
|
FILE *f = fopen(path.c_str(), "rb");
|
||||||
if(f)
|
if(f)
|
||||||
|
@ -38,7 +38,7 @@ namespace fs
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t GetFileSize(std::string path)
|
inline size_t GetFileSize(const std::string &path)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(path.c_str(), "rb");
|
FILE *f = fopen(path.c_str(), "rb");
|
||||||
if(f)
|
if(f)
|
||||||
|
@ -52,11 +52,11 @@ namespace fs
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveFile(std::string p1, std::string p2);
|
void MoveFile(const std::string &p1, const std::string &p2);
|
||||||
void CopyFile(std::string p, std::string np);
|
void CopyFile(const std::string &p, const std::string &np);
|
||||||
|
|
||||||
void MoveDirectory(std::string d, std::string nd);
|
void MoveDirectory(const std::string &d, const std::string &nd);
|
||||||
void CopyDirectory(std::string d, std::string nd);
|
void CopyDirectory(const std::string &d, const std::string &nd);
|
||||||
|
|
||||||
#define FS_FOR(dir, name_var, path_var, ...) \
|
#define FS_FOR(dir, name_var, path_var, ...) \
|
||||||
DIR *dp = opendir(dir.c_str()); \
|
DIR *dp = opendir(dir.c_str()); \
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace hb
|
||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static HbTargetParams Create(std::string nro_path, std::string nro_argv, bool target_once)
|
inline static HbTargetParams Create(const std::string &nro_path, const std::string &nro_argv, bool target_once)
|
||||||
{
|
{
|
||||||
HbTargetParams params = {};
|
HbTargetParams params = {};
|
||||||
params.magic = UL_HB_HBTARGET_MAGIC_U32;
|
params.magic = UL_HB_HBTARGET_MAGIC_U32;
|
||||||
|
|
|
@ -89,14 +89,4 @@ inline void Panic(std::string msg)
|
||||||
// TODO: non-console panic...?
|
// TODO: non-console panic...?
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void HandleECSMain()
|
#define UL_R_TRY(expr) { auto _tmp_rc = (expr); if(R_FAILED(_tmp_rc)) { fatalThrow(_tmp_rc); } }
|
||||||
{
|
|
||||||
u64 this_app_id = 0;
|
|
||||||
svcGetInfo(&this_app_id, InfoType_ProgramId, CUR_PROCESS_HANDLE, 0);
|
|
||||||
|
|
||||||
ldrShellInitialize();
|
|
||||||
serviceDispatchIn(ldrShellGetServiceSession(), 65001, this_app_id);
|
|
||||||
ldrShellExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UL_R_TRY(expr) { auto _tmp_rc = (expr); if(R_FAILED(_tmp_rc)) { fatalThrow(_tmp_rc); } }
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace res
|
||||||
RES_DEFINE(InvalidJSONFile, 1)
|
RES_DEFINE(InvalidJSONFile, 1)
|
||||||
RES_MODULE_END
|
RES_MODULE_END
|
||||||
|
|
||||||
RES_MODULE_BEGIN(QDaemon, 3)
|
RES_MODULE_BEGIN(Daemon, 3)
|
||||||
RES_DEFINE(ApplicationActive, 1)
|
RES_DEFINE(ApplicationActive, 1)
|
||||||
RES_DEFINE(InvalidSelectedUser, 2)
|
RES_DEFINE(InvalidSelectedUser, 2)
|
||||||
RES_DEFINE(AlreadyQueued, 3)
|
RES_DEFINE(AlreadyQueued, 3)
|
||||||
|
|
|
@ -5,7 +5,12 @@
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
std::string Format128NintendoStyle(AccountUid value);
|
std::string Format128NintendoStyle(AccountUid value);
|
||||||
u64 Get64FromString(std::string val);
|
|
||||||
|
inline u64 Get64FromString(const std::string &val)
|
||||||
|
{
|
||||||
|
return strtoull(val.c_str(), nullptr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
std::string FormatApplicationId(u64 app_id);
|
std::string FormatApplicationId(u64 app_id);
|
||||||
std::string FormatResultDisplay(Result rc);
|
std::string FormatResultDisplay(Result rc);
|
||||||
std::string FormatResultHex(Result rc);
|
std::string FormatResultHex(Result rc);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
ResultWith<JSON> LoadJSONFromFile(std::string path);
|
ResultWith<JSON> LoadJSONFromFile(const std::string &path);
|
||||||
std::string GetCurrentTime();
|
std::string GetCurrentTime();
|
||||||
u32 GetBatteryLevel();
|
u32 GetBatteryLevel();
|
||||||
bool IsCharging();
|
bool IsCharging();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
inline bool StringEndsWith(std::string const &value, std::string const &ending)
|
inline bool StringEndsWith(const std::string &value, const std::string &ending)
|
||||||
{
|
{
|
||||||
if(ending.size() > value.size()) return false;
|
if(ending.size() > value.size()) return false;
|
||||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||||
|
|
91
uLaunch/source/am/am_DaemonMenuInteraction.cpp
Normal file
91
uLaunch/source/am/am_DaemonMenuInteraction.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#include <am/am_DaemonMenuInteraction.hpp>
|
||||||
|
#include <fs/fs_Stdio.hpp>
|
||||||
|
#include <am/am_LibraryApplet.hpp>
|
||||||
|
|
||||||
|
namespace am
|
||||||
|
{
|
||||||
|
Service daemon_private_srv;
|
||||||
|
|
||||||
|
#define UL_AM_LOOP_TRY_WITH(...) { \
|
||||||
|
Result rc = 0; \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
svcSleepThread(10'000'000); \
|
||||||
|
} while(R_FAILED(rc)); \
|
||||||
|
return rc; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UL_AM_WAIT_WITH(...) { \
|
||||||
|
if(wait) { UL_AM_LOOP_TRY_WITH(__VA_ARGS__) } \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
Result rc = 0; \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
return rc; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UL_AM_WAIT(expr) UL_AM_WAIT_WITH(rc = (expr);)
|
||||||
|
|
||||||
|
ResultWith<MenuStartMode> Menu_ProcessInput()
|
||||||
|
{
|
||||||
|
LibAppletArgs in_args;
|
||||||
|
auto rc = Menu_DaemonReadImpl(&in_args, sizeof(LibAppletArgs), false);
|
||||||
|
return MakeResultWith(rc, (MenuStartMode)in_args.LaVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Menu_InitializeDaemonService()
|
||||||
|
{
|
||||||
|
if(serviceIsActive(&daemon_private_srv)) return 0;
|
||||||
|
return smGetService(&daemon_private_srv, AM_DAEMON_PRIVATE_SERVICE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultWith<MenuMessage> Menu_GetLatestMenuMessage()
|
||||||
|
{
|
||||||
|
u32 outmsg = 0;
|
||||||
|
auto rc = serviceDispatchOut(&daemon_private_srv, 0, outmsg);
|
||||||
|
return MakeResultWith(rc, (MenuMessage)outmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MenuIsHomePressed()
|
||||||
|
{
|
||||||
|
auto [rc, msg] = Menu_GetLatestMenuMessage();
|
||||||
|
if(R_FAILED(rc)) return false;
|
||||||
|
return (msg == MenuMessage::HomeRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu_FinalizeDaemonService()
|
||||||
|
{
|
||||||
|
serviceClose(&daemon_private_srv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Daemon_MenuWriteImpl(void *data, size_t size, bool wait)
|
||||||
|
UL_AM_WAIT(LibraryAppletSend(data, size))
|
||||||
|
|
||||||
|
Result Daemon_MenuReadImpl(void *data, size_t size, bool wait)
|
||||||
|
UL_AM_WAIT(LibraryAppletRead(data, size))
|
||||||
|
|
||||||
|
Result Menu_DaemonWriteImpl(void *data, size_t size, bool wait)
|
||||||
|
UL_AM_WAIT_WITH(
|
||||||
|
AppletStorage st;
|
||||||
|
rc = appletCreateStorage(&st, size);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
rc = appletStorageWrite(&st, 0, data, size);
|
||||||
|
if(R_SUCCEEDED(rc)) rc = appletPushOutData(&st);
|
||||||
|
appletStorageClose(&st);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Result Menu_DaemonReadImpl(void *data, size_t size, bool wait)
|
||||||
|
UL_AM_WAIT_WITH(
|
||||||
|
AppletStorage st;
|
||||||
|
rc = appletPopInData(&st);
|
||||||
|
if(R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
rc = appletStorageRead(&st, 0, data, size);
|
||||||
|
appletStorageClose(&st);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -2,8 +2,30 @@
|
||||||
|
|
||||||
namespace am
|
namespace am
|
||||||
{
|
{
|
||||||
AppletHolder applet_holder;
|
static AppletHolder applet_holder;
|
||||||
AppletId applet_lastid;
|
static AppletId applet_menuid = InvalidAppletId;
|
||||||
|
static AppletId applet_lastid = InvalidAppletId;
|
||||||
|
|
||||||
|
static std::map<u64, AppletId> applet_id_table =
|
||||||
|
{
|
||||||
|
{ 0x0100000000001001, AppletId_auth },
|
||||||
|
{ 0x0100000000001002, AppletId_cabinet },
|
||||||
|
{ 0x0100000000001003, AppletId_controller },
|
||||||
|
{ 0x0100000000001004, AppletId_dataErase },
|
||||||
|
{ 0x0100000000001005, AppletId_error },
|
||||||
|
{ 0x0100000000001006, AppletId_netConnect },
|
||||||
|
{ 0x0100000000001007, AppletId_playerSelect },
|
||||||
|
{ 0x0100000000001008, AppletId_swkbd },
|
||||||
|
{ 0x0100000000001009, AppletId_miiEdit },
|
||||||
|
{ 0x010000000000100A, AppletId_web },
|
||||||
|
{ 0x010000000000100B, AppletId_shop },
|
||||||
|
{ 0x010000000000100D, AppletId_photoViewer },
|
||||||
|
{ 0x010000000000100E, AppletId_set },
|
||||||
|
{ 0x010000000000100F, AppletId_offlineWeb },
|
||||||
|
{ 0x0100000000001010, AppletId_loginShare },
|
||||||
|
{ 0x0100000000001011, AppletId_wifiWebAuth },
|
||||||
|
{ 0x0100000000001013, AppletId_myPage }
|
||||||
|
};
|
||||||
|
|
||||||
bool LibraryAppletIsActive()
|
bool LibraryAppletIsActive()
|
||||||
{
|
{
|
||||||
|
@ -12,9 +34,14 @@ namespace am
|
||||||
return !appletHolderCheckFinished(&applet_holder);
|
return !appletHolderCheckFinished(&applet_holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibraryAppletIsQMenu()
|
void LibraryAppletSetMenuAppletId(AppletId id)
|
||||||
{
|
{
|
||||||
return (LibraryAppletIsActive() && (LibraryAppletGetId() == QMenuAppletId));
|
applet_menuid = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LibraryAppletIsMenu()
|
||||||
|
{
|
||||||
|
return (LibraryAppletIsActive() && (applet_menuid != InvalidAppletId) && (LibraryAppletGetId() == applet_menuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryAppletTerminate()
|
void LibraryAppletTerminate()
|
||||||
|
@ -55,7 +82,7 @@ namespace am
|
||||||
return LibraryAppletStart(AppletId_web, web->version, &web->arg, sizeof(web->arg));
|
return LibraryAppletStart(AppletId_web, web->version, &web->arg, sizeof(web->arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LibraryAppletQMenuLaunchWith(AppletId id, u32 la_version, std::function<void(AppletHolder*)> on_prepare, std::function<void(AppletHolder*)> on_finish, std::function<bool()> on_wait)
|
Result LibraryAppletDaemonLaunchWith(AppletId id, u32 la_version, std::function<void(AppletHolder*)> on_prepare, std::function<void(AppletHolder*)> on_finish, std::function<bool()> on_wait)
|
||||||
{
|
{
|
||||||
if(LibraryAppletIsActive()) LibraryAppletTerminate();
|
if(LibraryAppletIsActive()) LibraryAppletTerminate();
|
||||||
appletHolderClose(&applet_holder);
|
appletHolderClose(&applet_holder);
|
||||||
|
@ -73,17 +100,35 @@ namespace am
|
||||||
LibraryAppletTerminate();
|
LibraryAppletTerminate();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
svcSleepThread(10'000'000);
|
svcSleepThread(10'000'000l);
|
||||||
}
|
}
|
||||||
on_finish(&applet_holder);
|
on_finish(&applet_holder);
|
||||||
appletHolderClose(&applet_holder);
|
appletHolderClose(&applet_holder);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 LibraryAppletGetProgramIdForAppletId(AppletId id)
|
||||||
|
{
|
||||||
|
for(auto &[program_id, applet_id] : applet_id_table)
|
||||||
|
{
|
||||||
|
if(applet_id == id) return program_id;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletId LibraryAppletGetAppletIdForProgramId(u64 id)
|
||||||
|
{
|
||||||
|
for(auto &[program_id, applet_id] : applet_id_table)
|
||||||
|
{
|
||||||
|
if(program_id == id) return applet_id;
|
||||||
|
}
|
||||||
|
return InvalidAppletId;
|
||||||
|
}
|
||||||
|
|
||||||
AppletId LibraryAppletGetId()
|
AppletId LibraryAppletGetId()
|
||||||
{
|
{
|
||||||
auto idcopy = applet_lastid;
|
auto idcopy = applet_lastid;
|
||||||
if(!LibraryAppletIsActive()) applet_lastid = (AppletId)0; // Invalid
|
if(!LibraryAppletIsActive()) applet_lastid = InvalidAppletId;
|
||||||
return idcopy;
|
return idcopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,120 +0,0 @@
|
||||||
#include <am/am_QCommunications.hpp>
|
|
||||||
#include <fs/fs_Stdio.hpp>
|
|
||||||
#include <am/am_LibraryApplet.hpp>
|
|
||||||
|
|
||||||
namespace am
|
|
||||||
{
|
|
||||||
Service daemon_srv;
|
|
||||||
|
|
||||||
#define UL_AM_LOOP_TRY_WITH(...) { \
|
|
||||||
Result rc = 0; \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
svcSleepThread(10'000'000); \
|
|
||||||
} while(R_FAILED(rc)); \
|
|
||||||
return rc; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UL_AM_WAIT_WITH(...) { \
|
|
||||||
if(wait) { UL_AM_LOOP_TRY_WITH(__VA_ARGS__) } \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
Result rc = 0; \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
return rc; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UL_AM_WAIT(expr) UL_AM_WAIT_WITH(rc = (expr);)
|
|
||||||
|
|
||||||
Result QDaemon_LaunchQMenu(QMenuStartMode mode, QDaemonStatus status)
|
|
||||||
{
|
|
||||||
return LibraryAppletStart(QMenuAppletId, (u32)mode, &status, sizeof(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Result QDaemon_LaunchQHbTarget(hb::HbTargetParams input)
|
|
||||||
{
|
|
||||||
return LibraryAppletStart(QHbTargetAppletId, (u32)am::Magic, &input, sizeof(input));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Result QLibraryAppletReadStorage(void *data, size_t size)
|
|
||||||
{
|
|
||||||
return QMenu_QDaemonReadImpl(data, size, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result QApplicationReadStorage(void *data, size_t size)
|
|
||||||
{
|
|
||||||
AppletStorage st;
|
|
||||||
auto rc = appletPopLaunchParameter(&st, AppletLaunchParameterKind_UserChannel);
|
|
||||||
if(R_SUCCEEDED(rc))
|
|
||||||
{
|
|
||||||
rc = appletStorageRead(&st, 0, data, size);
|
|
||||||
appletStorageClose(&st);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultWith<QMenuStartMode> QMenu_ProcessInput()
|
|
||||||
{
|
|
||||||
LibAppletArgs in_args;
|
|
||||||
auto rc = QLibraryAppletReadStorage(&in_args, sizeof(LibAppletArgs));
|
|
||||||
return MakeResultWith(rc, (QMenuStartMode)in_args.LaVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result QMenu_InitializeDaemonService()
|
|
||||||
{
|
|
||||||
if(serviceIsActive(&daemon_srv)) return 0;
|
|
||||||
return smGetService(&daemon_srv, AM_QDAEMON_SERVICE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultWith<QMenuMessage> QMenu_GetLatestQMenuMessage()
|
|
||||||
{
|
|
||||||
u32 outmsg = 0;
|
|
||||||
auto rc = serviceDispatchOut(&daemon_srv, 0, outmsg);
|
|
||||||
return MakeResultWith(rc, (QMenuMessage)outmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QMenuIsHomePressed()
|
|
||||||
{
|
|
||||||
auto [rc, msg] = QMenu_GetLatestQMenuMessage();
|
|
||||||
if(R_FAILED(rc)) return false;
|
|
||||||
return (msg == QMenuMessage::HomeRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QMenu_FinalizeDaemonService()
|
|
||||||
{
|
|
||||||
serviceClose(&daemon_srv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result QDaemon_QMenuWriteImpl(void *data, size_t size, bool wait)
|
|
||||||
UL_AM_WAIT(LibraryAppletSend(data, size))
|
|
||||||
|
|
||||||
Result QDaemon_QMenuReadImpl(void *data, size_t size, bool wait)
|
|
||||||
UL_AM_WAIT(LibraryAppletRead(data, size))
|
|
||||||
|
|
||||||
Result QMenu_QDaemonWriteImpl(void *data, size_t size, bool wait)
|
|
||||||
UL_AM_WAIT_WITH(
|
|
||||||
AppletStorage st;
|
|
||||||
rc = appletCreateStorage(&st, size);
|
|
||||||
if(R_SUCCEEDED(rc))
|
|
||||||
{
|
|
||||||
rc = appletStorageWrite(&st, 0, data, size);
|
|
||||||
if(R_SUCCEEDED(rc)) rc = appletPushOutData(&st);
|
|
||||||
appletStorageClose(&st);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
Result QMenu_QDaemonReadImpl(void *data, size_t size, bool wait)
|
|
||||||
UL_AM_WAIT_WITH(
|
|
||||||
AppletStorage st;
|
|
||||||
rc = appletPopInData(&st);
|
|
||||||
if(R_SUCCEEDED(rc))
|
|
||||||
{
|
|
||||||
rc = appletStorageRead(&st, 0, data, size);
|
|
||||||
appletStorageClose(&st);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace cfg
|
namespace cfg
|
||||||
{
|
{
|
||||||
void CacheHomebrew(std::string nro_path)
|
void CacheHomebrew(const std::string &nro_path)
|
||||||
{
|
{
|
||||||
auto nroimg = GetNROCacheIconPath(nro_path);
|
auto nroimg = GetNROCacheIconPath(nro_path);
|
||||||
FILE *f = fopen(nro_path.c_str(), "rb");
|
FILE *f = fopen(nro_path.c_str(), "rb");
|
||||||
|
@ -39,7 +39,7 @@ namespace cfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TitleRecord> QueryAllHomebrew(std::string base)
|
std::vector<TitleRecord> QueryAllHomebrew(const std::string &base)
|
||||||
{
|
{
|
||||||
std::vector<TitleRecord> nros;
|
std::vector<TitleRecord> nros;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ namespace cfg
|
||||||
delete[] recordbuf;
|
delete[] recordbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CacheAllHomebrew(std::string hb_base_path)
|
static void CacheAllHomebrew(const std::string &hb_base_path)
|
||||||
{
|
{
|
||||||
FS_FOR(hb_base_path, name, path,
|
FS_FOR(hb_base_path, name, path,
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ namespace cfg
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
void CacheEverything(std::string hb_base_path)
|
void CacheEverything(const std::string &hb_base_path)
|
||||||
{
|
{
|
||||||
CacheInstalledTitles();
|
CacheInstalledTitles();
|
||||||
CacheAllHomebrew(hb_base_path);
|
CacheAllHomebrew(hb_base_path);
|
||||||
|
@ -188,7 +188,7 @@ namespace cfg
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
Theme LoadTheme(std::string base_name)
|
Theme LoadTheme(const std::string &base_name)
|
||||||
{
|
{
|
||||||
Theme theme = {};
|
Theme theme = {};
|
||||||
theme.base_name = base_name;
|
theme.base_name = base_name;
|
||||||
|
@ -223,7 +223,7 @@ namespace cfg
|
||||||
return themes;
|
return themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetAssetByTheme(Theme &base, std::string resource_base)
|
std::string GetAssetByTheme(const Theme &base, const std::string &resource_base)
|
||||||
{
|
{
|
||||||
auto base_res = base.path + "/" + resource_base;
|
auto base_res = base.path + "/" + resource_base;
|
||||||
if(fs::ExistsFile(base_res)) return base_res;
|
if(fs::ExistsFile(base_res)) return base_res;
|
||||||
|
@ -232,12 +232,12 @@ namespace cfg
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetLanguageJSONPath(std::string lang)
|
std::string GetLanguageJSONPath(const std::string &lang)
|
||||||
{
|
{
|
||||||
return UL_BASE_SD_DIR "/lang/" + lang + ".json";
|
return UL_BASE_SD_DIR "/lang/" + lang + ".json";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetLanguageString(JSON &lang, JSON &def, std::string name)
|
std::string GetLanguageString(const JSON &lang, const JSON &def, const std::string &name)
|
||||||
{
|
{
|
||||||
auto str = lang.value(name, "");
|
auto str = lang.value(name, "");
|
||||||
if(str.empty()) str = def.value(name, "");
|
if(str.empty()) str = def.value(name, "");
|
||||||
|
@ -246,29 +246,36 @@ namespace cfg
|
||||||
|
|
||||||
Config CreateNewAndLoadConfig()
|
Config CreateNewAndLoadConfig()
|
||||||
{
|
{
|
||||||
Config cfg = {};
|
// Default constructor sets everything
|
||||||
cfg.system_title_override_enabled = false; // Due to ban risk, have it disabled by default.
|
Config cfg;
|
||||||
cfg.viewer_usb_enabled = false; // Do not enable this by default due to conflicts with USB homebrew
|
|
||||||
cfg.theme_name = ""; // Default theme (none)
|
|
||||||
SaveConfig(cfg);
|
SaveConfig(cfg);
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config LoadConfig()
|
Config LoadConfig()
|
||||||
{
|
{
|
||||||
Config cfg = {};
|
// Default constructor sets everything
|
||||||
|
Config cfg;
|
||||||
auto [rc, cfgjson] = util::LoadJSONFromFile(CFG_CONFIG_JSON);
|
auto [rc, cfgjson] = util::LoadJSONFromFile(CFG_CONFIG_JSON);
|
||||||
if(R_SUCCEEDED(rc))
|
if(R_SUCCEEDED(rc))
|
||||||
{
|
{
|
||||||
cfg.theme_name = cfgjson.value("theme_name", "");
|
cfg.theme_name = cfgjson.value("theme_name", "");
|
||||||
cfg.system_title_override_enabled = cfgjson.value("system_title_override_enabled", false);
|
cfg.system_title_override_enabled = cfgjson.value("system_title_override_enabled", false);
|
||||||
cfg.viewer_usb_enabled = cfgjson.value("viewer_usb_enabled", false);
|
cfg.viewer_usb_enabled = cfgjson.value("viewer_usb_enabled", false);
|
||||||
|
auto menu_id_str = cfgjson.value("menu_program_id", "");
|
||||||
|
if(!menu_id_str.empty()) cfg.menu_program_id = util::Get64FromString(menu_id_str);
|
||||||
|
auto hb_applet_id_str = cfgjson.value("homebrew_applet_program_id", "");
|
||||||
|
if(!hb_applet_id_str.empty()) cfg.homebrew_applet_program_id = util::Get64FromString(hb_applet_id_str);
|
||||||
|
auto hb_title_id_str = cfgjson.value("homebrew_title_application_id", "");
|
||||||
|
if(!hb_title_id_str.empty()) cfg.homebrew_title_application_id = util::Get64FromString(hb_title_id_str);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fs::DeleteFile(CFG_CONFIG_JSON);
|
fs::DeleteFile(CFG_CONFIG_JSON);
|
||||||
return CreateNewAndLoadConfig();
|
return CreateNewAndLoadConfig();
|
||||||
}
|
}
|
||||||
|
// Doing this saves any fields not set previously
|
||||||
|
SaveConfig(cfg);
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,13 +285,15 @@ namespace cfg
|
||||||
return LoadConfig();
|
return LoadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveConfig(Config &cfg)
|
void SaveConfig(const Config &cfg)
|
||||||
{
|
{
|
||||||
fs::DeleteFile(CFG_CONFIG_JSON);
|
fs::DeleteFile(CFG_CONFIG_JSON);
|
||||||
JSON j = JSON::object();
|
JSON j = JSON::object();
|
||||||
j["theme_name"] = cfg.theme_name;
|
j["theme_name"] = cfg.theme_name;
|
||||||
j["system_title_override_enabled"] = cfg.system_title_override_enabled;
|
j["system_title_override_enabled"] = cfg.system_title_override_enabled;
|
||||||
j["viewer_usb_enabled"] = cfg.viewer_usb_enabled;
|
j["menu_program_id"] = util::FormatApplicationId(cfg.menu_program_id);
|
||||||
|
j["homebrew_applet_program_id"] = util::FormatApplicationId(cfg.homebrew_applet_program_id);
|
||||||
|
j["homebrew_title_application_id"] = util::FormatApplicationId(cfg.homebrew_title_application_id);
|
||||||
std::ofstream ofs(CFG_CONFIG_JSON);
|
std::ofstream ofs(CFG_CONFIG_JSON);
|
||||||
ofs << std::setw(4) << j;
|
ofs << std::setw(4) << j;
|
||||||
ofs.close();
|
ofs.close();
|
||||||
|
@ -353,7 +362,7 @@ namespace cfg
|
||||||
fs::DeleteFile(json);
|
fs::DeleteFile(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MoveTitleToDirectory(TitleList &list, u64 app_id, std::string folder)
|
bool MoveTitleToDirectory(TitleList &list, u64 app_id, const std::string &folder)
|
||||||
{
|
{
|
||||||
bool title_found = false;
|
bool title_found = false;
|
||||||
TitleRecord record_copy = {};
|
TitleRecord record_copy = {};
|
||||||
|
@ -421,7 +430,7 @@ namespace cfg
|
||||||
return title_found;
|
return title_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MoveRecordTo(TitleList &list, TitleRecord record, std::string folder)
|
bool MoveRecordTo(TitleList &list, TitleRecord record, const std::string &folder)
|
||||||
{
|
{
|
||||||
bool title_found = false;
|
bool title_found = false;
|
||||||
TitleRecord record_copy = {};
|
TitleRecord record_copy = {};
|
||||||
|
@ -518,7 +527,7 @@ namespace cfg
|
||||||
return title_found;
|
return title_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleFolder &FindFolderByName(TitleList &list, std::string name)
|
TitleFolder &FindFolderByName(TitleList &list, const std::string &name)
|
||||||
{
|
{
|
||||||
if(!name.empty())
|
if(!name.empty())
|
||||||
{
|
{
|
||||||
|
@ -531,7 +540,7 @@ namespace cfg
|
||||||
return list.root;
|
return list.root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenameFolder(TitleList &list, std::string old_name, std::string new_name)
|
void RenameFolder(TitleList &list, const std::string &old_name, const std::string &new_name)
|
||||||
{
|
{
|
||||||
auto &folder = FindFolderByName(list, old_name);
|
auto &folder = FindFolderByName(list, old_name);
|
||||||
if(!folder.name.empty())
|
if(!folder.name.empty())
|
||||||
|
@ -706,7 +715,7 @@ namespace cfg
|
||||||
return UL_BASE_SD_DIR "/title/" + strappid + ".jpg";
|
return UL_BASE_SD_DIR "/title/" + strappid + ".jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetNROCacheIconPath(std::string path)
|
std::string GetNROCacheIconPath(const std::string &path)
|
||||||
{
|
{
|
||||||
char pathcopy[FS_MAX_PATH] = {0};
|
char pathcopy[FS_MAX_PATH] = {0};
|
||||||
strcpy(pathcopy, path.c_str());
|
strcpy(pathcopy, path.c_str());
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace db
|
||||||
fsdevCommitDevice(UL_DB_MOUNT_NAME);
|
fsdevCommitDevice(UL_DB_MOUNT_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultWith<PassBlock> PackPassword(AccountUid uid, std::string pass)
|
ResultWith<PassBlock> PackPassword(AccountUid uid, const std::string &pass)
|
||||||
{
|
{
|
||||||
PassBlock pb = {};
|
PassBlock pb = {};
|
||||||
if((pass.length() > 15) || (pass.empty())) return MakeResultWith(RES_VALUE(Db, InvalidPasswordLength), pb);
|
if((pass.length() > 15) || (pass.empty())) return MakeResultWith(RES_VALUE(Db, InvalidPasswordLength), pb);
|
||||||
|
|
|
@ -3,53 +3,53 @@
|
||||||
|
|
||||||
namespace fs
|
namespace fs
|
||||||
{
|
{
|
||||||
static bool ExistsImpl(size_t st_mode, std::string path)
|
static bool ExistsImpl(size_t st_mode, const std::string &path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
return (stat(path.c_str(), &st) == 0) && (st.st_mode & st_mode);
|
return (stat(path.c_str(), &st) == 0) && (st.st_mode & st_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExistsFile(std::string path)
|
bool ExistsFile(const std::string &path)
|
||||||
{
|
{
|
||||||
return ExistsImpl(S_IFREG, path);
|
return ExistsImpl(S_IFREG, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExistsDirectory(std::string path)
|
bool ExistsDirectory(const std::string &path)
|
||||||
{
|
{
|
||||||
return ExistsImpl(S_IFDIR, path);
|
return ExistsImpl(S_IFDIR, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateDirectory(std::string path)
|
void CreateDirectory(const std::string &path)
|
||||||
{
|
{
|
||||||
mkdir(path.c_str(), 777);
|
mkdir(path.c_str(), 777);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateFile(std::string path)
|
void CreateFile(const std::string &path)
|
||||||
{
|
{
|
||||||
fsdevCreateFile(path.c_str(), 0, 0);
|
fsdevCreateFile(path.c_str(), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateConcatenationFile(std::string path)
|
void CreateConcatenationFile(const std::string &path)
|
||||||
{
|
{
|
||||||
fsdevCreateFile(path.c_str(), 0, FsCreateOption_BigFile);
|
fsdevCreateFile(path.c_str(), 0, FsCreateOption_BigFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteDirectory(std::string path)
|
void DeleteDirectory(const std::string &path)
|
||||||
{
|
{
|
||||||
fsdevDeleteDirectoryRecursively(path.c_str());
|
fsdevDeleteDirectoryRecursively(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteFile(std::string path)
|
void DeleteFile(const std::string &path)
|
||||||
{
|
{
|
||||||
remove(path.c_str());
|
remove(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveFile(std::string p1, std::string p2)
|
void MoveFile(const std::string &p1, const std::string &p2)
|
||||||
{
|
{
|
||||||
rename(p1.c_str(), p2.c_str());
|
rename(p1.c_str(), p2.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyFile(std::string p, std::string np)
|
void CopyFile(const std::string &p, const std::string &np)
|
||||||
{
|
{
|
||||||
FILE *inf = fopen(p.c_str(), "rb");
|
FILE *inf = fopen(p.c_str(), "rb");
|
||||||
if(inf)
|
if(inf)
|
||||||
|
@ -77,7 +77,7 @@ namespace fs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleDirectoryImpl(bool copy, std::string d, std::string nd)
|
static void HandleDirectoryImpl(bool copy, const std::string &d, const std::string &nd)
|
||||||
{
|
{
|
||||||
DIR *dp = opendir(d.c_str());
|
DIR *dp = opendir(d.c_str());
|
||||||
CreateDirectory(nd);
|
CreateDirectory(nd);
|
||||||
|
@ -102,12 +102,12 @@ namespace fs
|
||||||
if(!copy) DeleteDirectory(d);
|
if(!copy) DeleteDirectory(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveDirectory(std::string d, std::string nd)
|
void MoveDirectory(const std::string &d, const std::string &nd)
|
||||||
{
|
{
|
||||||
return HandleDirectoryImpl(false, d, nd);
|
return HandleDirectoryImpl(false, d, nd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyDirectory(std::string d, std::string nd)
|
void CopyDirectory(const std::string &d, const std::string &nd)
|
||||||
{
|
{
|
||||||
return HandleDirectoryImpl(true, d, nd);
|
return HandleDirectoryImpl(true, d, nd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,6 @@ namespace util
|
||||||
return strm.str();
|
return strm.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Get64FromString(std::string val)
|
|
||||||
{
|
|
||||||
return strtoull(val.c_str(), NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string FormatApplicationId(u64 app_id)
|
std::string FormatApplicationId(u64 app_id)
|
||||||
{
|
{
|
||||||
std::stringstream strm;
|
std::stringstream strm;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
ResultWith<JSON> LoadJSONFromFile(std::string path)
|
ResultWith<JSON> LoadJSONFromFile(const std::string &path)
|
||||||
{
|
{
|
||||||
JSON ret = JSON::object();
|
JSON ret = JSON::object();
|
||||||
if(fs::ExistsFile(path))
|
if(fs::ExistsFile(path))
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
class QMenuApplication : public pu::ui::Application
|
class MenuApplication : public pu::ui::Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Application::Application;
|
using Application::Application;
|
||||||
~QMenuApplication();
|
~MenuApplication();
|
||||||
PU_SMART_CTOR(QMenuApplication)
|
PU_SMART_CTOR(MenuApplication)
|
||||||
|
|
||||||
void OnLoad() override;
|
void OnLoad() override;
|
||||||
|
|
||||||
void SetInformation(am::QMenuStartMode mode, am::QDaemonStatus status);
|
void SetInformation(am::MenuStartMode mode, am::DaemonStatus status);
|
||||||
void LoadMenu();
|
void LoadMenu();
|
||||||
void LoadStartupMenu();
|
void LoadStartupMenu();
|
||||||
void LoadThemeMenu();
|
void LoadThemeMenu();
|
||||||
|
@ -81,14 +81,14 @@ namespace ui
|
||||||
|
|
||||||
void CommonMenuOnLoop();
|
void CommonMenuOnLoop();
|
||||||
private:
|
private:
|
||||||
am::QMenuStartMode stmode;
|
am::MenuStartMode stmode;
|
||||||
StartupLayout::Ref startupLayout;
|
StartupLayout::Ref startupLayout;
|
||||||
MenuLayout::Ref menuLayout;
|
MenuLayout::Ref menuLayout;
|
||||||
ThemeMenuLayout::Ref themeMenuLayout;
|
ThemeMenuLayout::Ref themeMenuLayout;
|
||||||
SettingsMenuLayout::Ref settingsMenuLayout;
|
SettingsMenuLayout::Ref settingsMenuLayout;
|
||||||
LanguagesMenuLayout::Ref languagesMenuLayout;
|
LanguagesMenuLayout::Ref languagesMenuLayout;
|
||||||
pu::ui::extras::Toast::Ref notifToast;
|
pu::ui::extras::Toast::Ref notifToast;
|
||||||
am::QDaemonStatus status;
|
am::DaemonStatus status;
|
||||||
JSON uijson;
|
JSON uijson;
|
||||||
JSON bgmjson;
|
JSON bgmjson;
|
||||||
bool bgm_loop;
|
bool bgm_loop;
|
||||||
|
@ -97,7 +97,7 @@ namespace ui
|
||||||
pu::audio::Music bgm;
|
pu::audio::Music bgm;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void QMenuApplication::CommonMenuOnLoop() // Stuff all menus should handle (currently just connected controllers)
|
inline void MenuApplication::CommonMenuOnLoop() // Stuff all menus should handle (currently just connected controllers)
|
||||||
{
|
{
|
||||||
if(!hidIsControllerConnected(CONTROLLER_HANDHELD) && !hidIsControllerConnected(CONTROLLER_PLAYER_1)) this->menuLayout->HandleControllerAppletOpen();
|
if(!hidIsControllerConnected(CONTROLLER_HANDHELD) && !hidIsControllerConnected(CONTROLLER_PLAYER_1)) this->menuLayout->HandleControllerAppletOpen();
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <ul_Include.hpp>
|
#include <ul_Include.hpp>
|
||||||
#include <am/am_QCommunications.hpp>
|
#include <am/am_DaemonMenuInteraction.hpp>
|
||||||
#include <db/db_Save.hpp>
|
#include <db/db_Save.hpp>
|
||||||
#include <pu/Plutonium>
|
#include <pu/Plutonium>
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,15 @@
|
||||||
#include <cfg/cfg_Config.hpp>
|
#include <cfg/cfg_Config.hpp>
|
||||||
#include <net/net_Service.hpp>
|
#include <net/net_Service.hpp>
|
||||||
#include <util/util_Misc.hpp>
|
#include <util/util_Misc.hpp>
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <os/os_HomeMenu.hpp>
|
#include <os/os_HomeMenu.hpp>
|
||||||
#include <util/util_Convert.hpp>
|
#include <util/util_Convert.hpp>
|
||||||
|
#include <am/am_LibraryApplet.hpp>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
u32 __nx_applet_type = AppletType_LibraryApplet; // Explicitly declare we're a library applet (need to do so for non-hbloader homebrew)
|
u32 __nx_applet_type = AppletType_LibraryApplet; // Explicitly declare we're a library applet (need to do so for non-hbloader homebrew)
|
||||||
|
TimeServiceType __nx_time_service_type = TimeServiceType_System;
|
||||||
size_t __nx_heap_size = 0xD000000; // 208MB heap
|
size_t __nx_heap_size = 0xD000000; // 208MB heap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ extern "C"
|
||||||
|
|
||||||
// Some global vars
|
// Some global vars
|
||||||
|
|
||||||
ui::QMenuApplication::Ref qapp;
|
ui::MenuApplication::Ref qapp;
|
||||||
cfg::TitleList list;
|
cfg::TitleList list;
|
||||||
std::vector<cfg::TitleRecord> homebrew;
|
std::vector<cfg::TitleRecord> homebrew;
|
||||||
cfg::Config config;
|
cfg::Config config;
|
||||||
|
@ -40,7 +42,7 @@ namespace qmenu
|
||||||
UL_R_TRY(setsysInitialize())
|
UL_R_TRY(setsysInitialize())
|
||||||
UL_R_TRY(setInitialize())
|
UL_R_TRY(setInitialize())
|
||||||
|
|
||||||
UL_R_TRY(am::QMenu_InitializeDaemonService())
|
UL_R_TRY(am::Menu_InitializeDaemonService())
|
||||||
|
|
||||||
// Load menu config and theme
|
// Load menu config and theme
|
||||||
config = cfg::EnsureConfig();
|
config = cfg::EnsureConfig();
|
||||||
|
@ -49,7 +51,7 @@ namespace qmenu
|
||||||
|
|
||||||
void Exit()
|
void Exit()
|
||||||
{
|
{
|
||||||
am::QMenu_FinalizeDaemonService();
|
am::Menu_FinalizeDaemonService();
|
||||||
|
|
||||||
setExit();
|
setExit();
|
||||||
setsysExit();
|
setsysExit();
|
||||||
|
@ -62,17 +64,17 @@ namespace qmenu
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
auto [rc, smode] = am::QMenu_ProcessInput();
|
auto [rc, smode] = am::Menu_ProcessInput();
|
||||||
if(R_SUCCEEDED(rc))
|
if(R_SUCCEEDED(rc))
|
||||||
{
|
{
|
||||||
am::QDaemonStatus status = {};
|
am::DaemonStatus status = {};
|
||||||
|
|
||||||
// Information block sent as an extra storage to QMenu.
|
// Information block sent as an extra storage to Menu.
|
||||||
am::QLibraryAppletReadStorage(&status, sizeof(status));
|
am::Menu_DaemonReadImpl(&status, sizeof(status), false);
|
||||||
|
|
||||||
// First read sent storages, then init the renderer (UI, which also inits RomFs), then init everything else
|
// First read sent storages, then init the renderer (UI, which also inits RomFs), then init everything else
|
||||||
|
|
||||||
if(smode != am::QMenuStartMode::Invalid)
|
if(smode != am::MenuStartMode::Invalid)
|
||||||
{
|
{
|
||||||
// Check if our RomFs file exists...
|
// Check if our RomFs file exists...
|
||||||
if(!fs::ExistsFile(MENU_ROMFS_BIN)) Panic("Unable to find RomFs binary: '" MENU_ROMFS_BIN "'");
|
if(!fs::ExistsFile(MENU_ROMFS_BIN)) Panic("Unable to find RomFs binary: '" MENU_ROMFS_BIN "'");
|
||||||
|
@ -107,12 +109,12 @@ int main()
|
||||||
renderoptions.InitRomFs = false; // We have loaded RomFs from an external file, so :P
|
renderoptions.InitRomFs = false; // We have loaded RomFs from an external file, so :P
|
||||||
|
|
||||||
auto renderer = pu::ui::render::Renderer::New(SDL_INIT_EVERYTHING, renderoptions, pu::ui::render::RendererHardwareFlags);
|
auto renderer = pu::ui::render::Renderer::New(SDL_INIT_EVERYTHING, renderoptions, pu::ui::render::RendererHardwareFlags);
|
||||||
qapp = ui::QMenuApplication::New(renderer);
|
qapp = ui::MenuApplication::New(renderer);
|
||||||
|
|
||||||
qapp->SetInformation(smode, status);
|
qapp->SetInformation(smode, status);
|
||||||
qapp->Prepare();
|
qapp->Prepare();
|
||||||
|
|
||||||
if(smode == am::QMenuStartMode::MenuApplicationSuspended) qapp->Show();
|
if(smode == am::MenuStartMode::MenuApplicationSuspended) qapp->Show();
|
||||||
else qapp->ShowWithFadeIn();
|
else qapp->ShowWithFadeIn();
|
||||||
|
|
||||||
// Exit RomFs manually, Plutonium won't do it for us since we're initializing it manually
|
// Exit RomFs manually, Plutonium won't do it for us since we're initializing it manually
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#include <ui/ui_LanguagesMenuLayout.hpp>
|
#include <ui/ui_LanguagesMenuLayout.hpp>
|
||||||
#include <os/os_Account.hpp>
|
#include <os/os_Account.hpp>
|
||||||
#include <util/util_Convert.hpp>
|
#include <util/util_Convert.hpp>
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <fs/fs_Stdio.hpp>
|
#include <fs/fs_Stdio.hpp>
|
||||||
#include <os/os_Misc.hpp>
|
#include <os/os_Misc.hpp>
|
||||||
#include <os/os_HomeMenu.hpp>
|
#include <os/os_HomeMenu.hpp>
|
||||||
#include <net/net_Service.hpp>
|
#include <net/net_Service.hpp>
|
||||||
#include <am/am_LibraryApplet.hpp>
|
#include <am/am_LibraryApplet.hpp>
|
||||||
|
|
||||||
extern ui::QMenuApplication::Ref qapp;
|
extern ui::MenuApplication::Ref qapp;
|
||||||
extern cfg::Theme theme;
|
extern cfg::Theme theme;
|
||||||
extern cfg::Config config;
|
extern cfg::Config config;
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ namespace ui
|
||||||
{
|
{
|
||||||
qapp->CommonMenuOnLoop();
|
qapp->CommonMenuOnLoop();
|
||||||
|
|
||||||
bool ret = am::QMenuIsHomePressed();
|
bool ret = am::MenuIsHomePressed();
|
||||||
if(down & KEY_B)
|
if(down & KEY_B)
|
||||||
{
|
{
|
||||||
qapp->FadeOut();
|
qapp->FadeOut();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <util/util_Misc.hpp>
|
#include <util/util_Misc.hpp>
|
||||||
|
|
||||||
extern u8 *app_buf;
|
extern u8 *app_buf;
|
||||||
|
@ -6,12 +6,12 @@ extern cfg::Theme theme;
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
QMenuApplication::~QMenuApplication()
|
MenuApplication::~MenuApplication()
|
||||||
{
|
{
|
||||||
pu::audio::Delete(this->bgm);
|
pu::audio::Delete(this->bgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::OnLoad()
|
void MenuApplication::OnLoad()
|
||||||
{
|
{
|
||||||
pu::ui::render::SetDefaultFont(cfg::GetAssetByTheme(theme, "ui/Font.ttf"));
|
pu::ui::render::SetDefaultFont(cfg::GetAssetByTheme(theme, "ui/Font.ttf"));
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace ui
|
||||||
|
|
||||||
switch(this->stmode)
|
switch(this->stmode)
|
||||||
{
|
{
|
||||||
case am::QMenuStartMode::StartupScreen:
|
case am::MenuStartMode::StartupScreen:
|
||||||
this->LoadStartupMenu();
|
this->LoadStartupMenu();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -53,88 +53,88 @@ namespace ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::SetInformation(am::QMenuStartMode mode, am::QDaemonStatus status)
|
void MenuApplication::SetInformation(am::MenuStartMode mode, am::DaemonStatus status)
|
||||||
{
|
{
|
||||||
this->stmode = mode;
|
this->stmode = mode;
|
||||||
this->status = status;
|
this->status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::LoadMenu()
|
void MenuApplication::LoadMenu()
|
||||||
{
|
{
|
||||||
this->menuLayout->SetUser(this->status.selected_user);
|
this->menuLayout->SetUser(this->status.selected_user);
|
||||||
this->LoadLayout(this->menuLayout);
|
this->LoadLayout(this->menuLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::LoadStartupMenu()
|
void MenuApplication::LoadStartupMenu()
|
||||||
{
|
{
|
||||||
this->StopPlayBGM();
|
this->StopPlayBGM();
|
||||||
this->startupLayout->ReloadMenu();
|
this->startupLayout->ReloadMenu();
|
||||||
this->LoadLayout(this->startupLayout);
|
this->LoadLayout(this->startupLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::LoadThemeMenu()
|
void MenuApplication::LoadThemeMenu()
|
||||||
{
|
{
|
||||||
this->themeMenuLayout->Reload();
|
this->themeMenuLayout->Reload();
|
||||||
this->LoadLayout(this->themeMenuLayout);
|
this->LoadLayout(this->themeMenuLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::LoadSettingsMenu()
|
void MenuApplication::LoadSettingsMenu()
|
||||||
{
|
{
|
||||||
this->settingsMenuLayout->Reload();
|
this->settingsMenuLayout->Reload();
|
||||||
this->LoadLayout(this->settingsMenuLayout);
|
this->LoadLayout(this->settingsMenuLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::LoadSettingsLanguagesMenu()
|
void MenuApplication::LoadSettingsLanguagesMenu()
|
||||||
{
|
{
|
||||||
this->languagesMenuLayout->Reload();
|
this->languagesMenuLayout->Reload();
|
||||||
this->LoadLayout(this->languagesMenuLayout);
|
this->LoadLayout(this->languagesMenuLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMenuApplication::IsSuspended()
|
bool MenuApplication::IsSuspended()
|
||||||
{
|
{
|
||||||
return this->IsTitleSuspended() || this->IsHomebrewSuspended();
|
return this->IsTitleSuspended() || this->IsHomebrewSuspended();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMenuApplication::IsTitleSuspended()
|
bool MenuApplication::IsTitleSuspended()
|
||||||
{
|
{
|
||||||
return this->status.app_id > 0;
|
return this->status.app_id > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMenuApplication::IsHomebrewSuspended()
|
bool MenuApplication::IsHomebrewSuspended()
|
||||||
{
|
{
|
||||||
return strlen(this->status.params.nro_path);
|
return strlen(this->status.params.nro_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMenuApplication::EqualsSuspendedHomebrewPath(std::string path)
|
bool MenuApplication::EqualsSuspendedHomebrewPath(std::string path)
|
||||||
{
|
{
|
||||||
return this->status.params.nro_path == path;
|
return this->status.params.nro_path == path;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 QMenuApplication::GetSuspendedApplicationId()
|
u64 MenuApplication::GetSuspendedApplicationId()
|
||||||
{
|
{
|
||||||
return this->status.app_id;
|
return this->status.app_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::NotifyEndSuspended()
|
void MenuApplication::NotifyEndSuspended()
|
||||||
{
|
{
|
||||||
// Blanking the whole status would also blank the selected user...
|
// Blanking the whole status would also blank the selected user...
|
||||||
this->status.params = {};
|
this->status.params = {};
|
||||||
this->status.app_id = 0;
|
this->status.app_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMenuApplication::LaunchFailed()
|
bool MenuApplication::LaunchFailed()
|
||||||
{
|
{
|
||||||
return (this->stmode == am::QMenuStartMode::MenuLaunchFailure);
|
return (this->stmode == am::MenuStartMode::MenuLaunchFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::ShowNotification(std::string text, u64 timeout)
|
void MenuApplication::ShowNotification(std::string text, u64 timeout)
|
||||||
{
|
{
|
||||||
this->EndOverlay();
|
this->EndOverlay();
|
||||||
this->notifToast->SetText(text);
|
this->notifToast->SetText(text);
|
||||||
this->StartOverlayWithTimeout(this->notifToast, timeout);
|
this->StartOverlayWithTimeout(this->notifToast, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::StartPlayBGM()
|
void MenuApplication::StartPlayBGM()
|
||||||
{
|
{
|
||||||
if(this->bgm != NULL)
|
if(this->bgm != NULL)
|
||||||
{
|
{
|
||||||
|
@ -144,22 +144,22 @@ namespace ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::StopPlayBGM()
|
void MenuApplication::StopPlayBGM()
|
||||||
{
|
{
|
||||||
if(this->bgm_fade_out_ms > 0) pu::audio::FadeOut(this->bgm_fade_out_ms);
|
if(this->bgm_fade_out_ms > 0) pu::audio::FadeOut(this->bgm_fade_out_ms);
|
||||||
else pu::audio::Stop();
|
else pu::audio::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMenuApplication::SetSelectedUser(AccountUid user_id)
|
void MenuApplication::SetSelectedUser(AccountUid user_id)
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::SetSelectedUser);
|
am::MenuCommandWriter writer(am::DaemonMessage::SetSelectedUser);
|
||||||
writer.Write<AccountUid>(user_id);
|
writer.Write<AccountUid>(user_id);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
memcpy(&this->status.selected_user, &user_id, sizeof(user_id));
|
memcpy(&this->status.selected_user, &user_id, sizeof(user_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountUid QMenuApplication::GetSelectedUser()
|
AccountUid MenuApplication::GetSelectedUser()
|
||||||
{
|
{
|
||||||
return this->status.selected_user;
|
return this->status.selected_user;
|
||||||
}
|
}
|
|
@ -5,12 +5,12 @@
|
||||||
#include <util/util_Misc.hpp>
|
#include <util/util_Misc.hpp>
|
||||||
#include <os/os_Misc.hpp>
|
#include <os/os_Misc.hpp>
|
||||||
#include <am/am_LibraryApplet.hpp>
|
#include <am/am_LibraryApplet.hpp>
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <os/os_HomeMenu.hpp>
|
#include <os/os_HomeMenu.hpp>
|
||||||
#include <fs/fs_Stdio.hpp>
|
#include <fs/fs_Stdio.hpp>
|
||||||
#include <net/net_Service.hpp>
|
#include <net/net_Service.hpp>
|
||||||
|
|
||||||
extern ui::QMenuApplication::Ref qapp;
|
extern ui::MenuApplication::Ref qapp;
|
||||||
extern cfg::TitleList list;
|
extern cfg::TitleList list;
|
||||||
extern std::vector<cfg::TitleRecord> homebrew;
|
extern std::vector<cfg::TitleRecord> homebrew;
|
||||||
extern cfg::Config config;
|
extern cfg::Config config;
|
||||||
|
@ -288,205 +288,215 @@ namespace ui
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((down & KEY_A) || (down & KEY_X) || (down & KEY_Y))
|
if((index == 0) && this->homebrew_mode)
|
||||||
{
|
{
|
||||||
if((index == 0) && this->homebrew_mode)
|
if(down & KEY_A)
|
||||||
{
|
{
|
||||||
|
pu::audio::Play(this->sfxTitleLaunch);
|
||||||
|
am::MenuCommandWriter writer(am::DaemonMessage::LaunchHomebrewLibraryApplet);
|
||||||
|
hb::HbTargetParams ipt = {};
|
||||||
|
strcpy(ipt.nro_path, MENU_HBMENU_NRO); // Launch normal hbmenu
|
||||||
|
strcpy(ipt.nro_argv, MENU_HBMENU_NRO);
|
||||||
|
writer.Write<hb::HbTargetParams>(ipt);
|
||||||
|
writer.FinishWrite();
|
||||||
|
|
||||||
|
qapp->StopPlayBGM();
|
||||||
|
qapp->CloseWithFadeOut();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 realidx = index;
|
||||||
|
if(this->homebrew_mode) realidx--;
|
||||||
|
if(this->homebrew_mode)
|
||||||
|
{
|
||||||
|
auto hb = homebrew[realidx];
|
||||||
if(down & KEY_A)
|
if(down & KEY_A)
|
||||||
{
|
{
|
||||||
pu::audio::Play(this->sfxTitleLaunch);
|
bool hblaunch = true;
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::LaunchHomebrewLibApplet);
|
if(qapp->IsHomebrewSuspended())
|
||||||
hb::HbTargetParams ipt = {};
|
{
|
||||||
strcpy(ipt.nro_path, MENU_HBMENU_NRO); // Launch normal hbmenu
|
if(qapp->EqualsSuspendedHomebrewPath(hb.nro_target.nro_path))
|
||||||
strcpy(ipt.nro_argv, MENU_HBMENU_NRO);
|
{
|
||||||
writer.Write<hb::HbTargetParams>(ipt);
|
if(this->mode == 1) this->mode = 2;
|
||||||
writer.FinishWrite();
|
hblaunch = false;
|
||||||
|
}
|
||||||
qapp->StopPlayBGM();
|
else
|
||||||
qapp->CloseWithFadeOut();
|
{
|
||||||
return;
|
hblaunch = false;
|
||||||
|
this->HandleCloseSuspended();
|
||||||
|
hblaunch = !qapp->IsHomebrewSuspended();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hblaunch) this->HandleHomebrewLaunch(hb);
|
||||||
|
}
|
||||||
|
else if(down & KEY_X)
|
||||||
|
{
|
||||||
|
if(qapp->IsSuspended())
|
||||||
|
{
|
||||||
|
if(qapp->EqualsSuspendedHomebrewPath(hb.nro_target.nro_path)) this->HandleCloseSuspended();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(down & KEY_Y)
|
||||||
|
{
|
||||||
|
if(!this->select_on) this->select_on = true;
|
||||||
|
this->itemsMenu->SetItemMultiselected(this->itemsMenu->GetSelectedItem(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 realidx = index;
|
auto &folder = cfg::FindFolderByName(list, this->curfolder);
|
||||||
if(this->homebrew_mode) realidx--;
|
s32 titleidx = realidx;
|
||||||
if(this->homebrew_mode)
|
if(this->curfolder.empty())
|
||||||
{
|
{
|
||||||
auto hb = homebrew[realidx];
|
if(realidx >= list.folders.size())
|
||||||
if(down & KEY_A)
|
|
||||||
{
|
{
|
||||||
bool hblaunch = true;
|
titleidx -= list.folders.size();
|
||||||
if(qapp->IsHomebrewSuspended())
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto foldr = list.folders[realidx];
|
||||||
|
if(down & KEY_A)
|
||||||
{
|
{
|
||||||
if(qapp->EqualsSuspendedHomebrewPath(hb.nro_target.nro_path))
|
this->MoveFolder(foldr.name, true);
|
||||||
|
}
|
||||||
|
else if(down & KEY_Y)
|
||||||
|
{
|
||||||
|
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "menu_rename_folder"), cfg::GetLanguageString(config.main_lang, config.default_lang, "menu_rename_folder_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
|
||||||
|
if(sopt == 0)
|
||||||
{
|
{
|
||||||
if(this->mode == 1) this->mode = 2;
|
SwkbdConfig swkbd;
|
||||||
hblaunch = false;
|
swkbdCreate(&swkbd, 0);
|
||||||
}
|
swkbdConfigSetGuideText(&swkbd, cfg::GetLanguageString(config.main_lang, config.default_lang, "swkbd_rename_folder_guide").c_str());
|
||||||
else
|
char dir[500] = {0};
|
||||||
{
|
auto rc = swkbdShow(&swkbd, dir, 500);
|
||||||
hblaunch = false;
|
swkbdClose(&swkbd);
|
||||||
this->HandleCloseSuspended();
|
if(R_SUCCEEDED(rc))
|
||||||
hblaunch = !qapp->IsHomebrewSuspended();
|
{
|
||||||
|
cfg::RenameFolder(list, foldr.name, dir);
|
||||||
|
this->MoveFolder(this->curfolder, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
titleidx = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(titleidx >= 0)
|
||||||
|
{
|
||||||
|
auto title = folder.titles[titleidx];
|
||||||
|
if(down & KEY_A)
|
||||||
|
{
|
||||||
|
bool titlelaunch = true;
|
||||||
|
|
||||||
|
if(qapp->IsSuspended())
|
||||||
|
{
|
||||||
|
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
|
||||||
|
{
|
||||||
|
if(qapp->EqualsSuspendedHomebrewPath(title.nro_target.nro_path))
|
||||||
|
{
|
||||||
|
if(this->mode == 1) this->mode = 2;
|
||||||
|
titlelaunch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if((cfg::TitleType)title.title_type == cfg::TitleType::Installed)
|
||||||
|
{
|
||||||
|
if(title.app_id == qapp->GetSuspendedApplicationId())
|
||||||
|
{
|
||||||
|
if(this->mode == 1) this->mode = 2;
|
||||||
|
titlelaunch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(titlelaunch)
|
||||||
|
{
|
||||||
|
// Homebrew launching code already does this checks later - doing this check only with installed titles
|
||||||
|
if((cfg::TitleType)title.title_type == cfg::TitleType::Installed)
|
||||||
|
{
|
||||||
|
titlelaunch = false;
|
||||||
|
this->HandleCloseSuspended();
|
||||||
|
titlelaunch = !qapp->IsSuspended();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(titlelaunch)
|
||||||
|
{
|
||||||
|
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew) this->HandleHomebrewLaunch(title);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pu::audio::Play(this->sfxTitleLaunch);
|
||||||
|
am::MenuCommandWriter writer(am::DaemonMessage::LaunchApplication);
|
||||||
|
writer.Write<u64>(title.app_id);
|
||||||
|
writer.FinishWrite();
|
||||||
|
|
||||||
|
am::MenuCommandResultReader reader;
|
||||||
|
if(reader && R_SUCCEEDED(reader.GetReadResult()))
|
||||||
|
{
|
||||||
|
qapp->StopPlayBGM();
|
||||||
|
qapp->CloseWithFadeOut();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto rc = reader.GetReadResult();
|
||||||
|
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "app_launch_error") + ": " + util::FormatResult(rc));
|
||||||
|
}
|
||||||
|
reader.FinishRead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(hblaunch) this->HandleHomebrewLaunch(hb);
|
|
||||||
}
|
}
|
||||||
else if(down & KEY_X)
|
else if(down & KEY_X)
|
||||||
{
|
{
|
||||||
if(qapp->IsSuspended())
|
if(qapp->IsSuspended())
|
||||||
{
|
{
|
||||||
if(qapp->EqualsSuspendedHomebrewPath(hb.nro_target.nro_path)) this->HandleCloseSuspended();
|
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
|
||||||
|
{
|
||||||
|
if(qapp->EqualsSuspendedHomebrewPath(title.nro_target.nro_path)) this->HandleCloseSuspended();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(title.app_id == qapp->GetSuspendedApplicationId()) this->HandleCloseSuspended();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(down & KEY_Y)
|
else if(down & KEY_Y)
|
||||||
{
|
{
|
||||||
if(!this->select_on) this->select_on = true;
|
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
|
||||||
this->itemsMenu->SetItemMultiselected(this->itemsMenu->GetSelectedItem(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto &folder = cfg::FindFolderByName(list, this->curfolder);
|
|
||||||
s32 titleidx = realidx;
|
|
||||||
if(this->curfolder.empty())
|
|
||||||
{
|
|
||||||
if(realidx >= list.folders.size())
|
|
||||||
{
|
{
|
||||||
titleidx -= list.folders.size();
|
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_options"), cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_action"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_move"), cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
|
||||||
}
|
if(sopt == 0)
|
||||||
else
|
|
||||||
{
|
|
||||||
auto foldr = list.folders[realidx];
|
|
||||||
if(down & KEY_A)
|
|
||||||
{
|
|
||||||
this->MoveFolder(foldr.name, true);
|
|
||||||
}
|
|
||||||
else if(down & KEY_Y)
|
|
||||||
{
|
|
||||||
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "menu_rename_folder"), cfg::GetLanguageString(config.main_lang, config.default_lang, "menu_rename_folder_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
|
|
||||||
if(sopt == 0)
|
|
||||||
{
|
|
||||||
SwkbdConfig swkbd;
|
|
||||||
swkbdCreate(&swkbd, 0);
|
|
||||||
swkbdConfigSetGuideText(&swkbd, cfg::GetLanguageString(config.main_lang, config.default_lang, "swkbd_rename_folder_guide").c_str());
|
|
||||||
char dir[500] = {0};
|
|
||||||
auto rc = swkbdShow(&swkbd, dir, 500);
|
|
||||||
swkbdClose(&swkbd);
|
|
||||||
if(R_SUCCEEDED(rc))
|
|
||||||
{
|
|
||||||
cfg::RenameFolder(list, foldr.name, dir);
|
|
||||||
this->MoveFolder(this->curfolder, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
titleidx = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(titleidx >= 0)
|
|
||||||
{
|
|
||||||
auto title = folder.titles[titleidx];
|
|
||||||
if(down & KEY_A)
|
|
||||||
{
|
|
||||||
bool titlelaunch = true;
|
|
||||||
|
|
||||||
if(qapp->IsSuspended())
|
|
||||||
{
|
|
||||||
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
|
|
||||||
{
|
|
||||||
if(qapp->EqualsSuspendedHomebrewPath(title.nro_target.nro_path))
|
|
||||||
{
|
|
||||||
if(this->mode == 1) this->mode = 2;
|
|
||||||
titlelaunch = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if((cfg::TitleType)title.title_type == cfg::TitleType::Installed)
|
|
||||||
{
|
|
||||||
if(title.app_id == qapp->GetSuspendedApplicationId())
|
|
||||||
{
|
|
||||||
if(this->mode == 1) this->mode = 2;
|
|
||||||
titlelaunch = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(titlelaunch)
|
|
||||||
{
|
|
||||||
// Homebrew launching code already does this checks later - doing this check only with installed titles
|
|
||||||
if((cfg::TitleType)title.title_type == cfg::TitleType::Installed)
|
|
||||||
{
|
|
||||||
titlelaunch = false;
|
|
||||||
this->HandleCloseSuspended();
|
|
||||||
titlelaunch = !qapp->IsSuspended();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(titlelaunch)
|
|
||||||
{
|
|
||||||
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew) this->HandleHomebrewLaunch(title);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pu::audio::Play(this->sfxTitleLaunch);
|
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::LaunchApplication);
|
|
||||||
writer.Write<u64>(title.app_id);
|
|
||||||
writer.FinishWrite();
|
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
|
||||||
if(reader && R_SUCCEEDED(reader.GetReadResult()))
|
|
||||||
{
|
|
||||||
qapp->StopPlayBGM();
|
|
||||||
qapp->CloseWithFadeOut();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto rc = reader.GetReadResult();
|
|
||||||
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "app_launch_error") + ": " + util::FormatResult(rc));
|
|
||||||
}
|
|
||||||
reader.FinishRead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(down & KEY_X)
|
|
||||||
{
|
|
||||||
if(qapp->IsSuspended())
|
|
||||||
{
|
|
||||||
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
|
|
||||||
{
|
|
||||||
if(qapp->EqualsSuspendedHomebrewPath(title.nro_target.nro_path)) this->HandleCloseSuspended();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(title.app_id == qapp->GetSuspendedApplicationId()) this->HandleCloseSuspended();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(down & KEY_Y)
|
|
||||||
{
|
|
||||||
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
|
|
||||||
{
|
|
||||||
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_options"), cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_action"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_move"), cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
|
|
||||||
if(sopt == 0)
|
|
||||||
{
|
|
||||||
if(!this->select_on) this->select_on = true;
|
|
||||||
this->itemsMenu->SetItemMultiselected(this->itemsMenu->GetSelectedItem(), true);
|
|
||||||
}
|
|
||||||
else if(sopt == 1)
|
|
||||||
{
|
|
||||||
auto sopt2 = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove"), cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
|
|
||||||
if(sopt2 == 0)
|
|
||||||
{
|
|
||||||
cfg::RemoveRecord(title);
|
|
||||||
folder.titles.erase(folder.titles.begin() + titleidx);
|
|
||||||
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove_ok"));
|
|
||||||
this->MoveFolder(this->curfolder, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if(!this->select_on) this->select_on = true;
|
if(!this->select_on) this->select_on = true;
|
||||||
this->itemsMenu->SetItemMultiselected(this->itemsMenu->GetSelectedItem(), true);
|
this->itemsMenu->SetItemMultiselected(this->itemsMenu->GetSelectedItem(), true);
|
||||||
}
|
}
|
||||||
|
else if(sopt == 1)
|
||||||
|
{
|
||||||
|
auto sopt2 = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove"), cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
|
||||||
|
if(sopt2 == 0)
|
||||||
|
{
|
||||||
|
cfg::RemoveRecord(title);
|
||||||
|
folder.titles.erase(folder.titles.begin() + titleidx);
|
||||||
|
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "entry_remove_ok"));
|
||||||
|
this->MoveFolder(this->curfolder, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!this->select_on) this->select_on = true;
|
||||||
|
this->itemsMenu->SetItemMultiselected(this->itemsMenu->GetSelectedItem(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(down & KEY_UP)
|
||||||
|
{
|
||||||
|
if((cfg::TitleType)title.title_type == cfg::TitleType::Installed)
|
||||||
|
{
|
||||||
|
auto sopt = qapp->CreateShowDialog("Homebrew title take-over", "Would you like to select this title for homebrew launching?\nIf selected, homebrew will be launched as an application over this title.", { "Yes", "Cancel" }, true);
|
||||||
|
if(sopt == 0)
|
||||||
|
{
|
||||||
|
config.homebrew_title_application_id = title.app_id;
|
||||||
|
cfg::SaveConfig(config);
|
||||||
|
qapp->ShowNotification("Done");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -669,7 +679,7 @@ namespace ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(am::QMenuIsHomePressed())
|
if(am::MenuIsHomePressed())
|
||||||
{
|
{
|
||||||
if(qapp->IsSuspended())
|
if(qapp->IsSuspended())
|
||||||
{
|
{
|
||||||
|
@ -713,10 +723,10 @@ namespace ui
|
||||||
if(this->rawalpha == 255)
|
if(this->rawalpha == 255)
|
||||||
{
|
{
|
||||||
this->bgSuspendedRaw->SetAlphaFactor(this->rawalpha);
|
this->bgSuspendedRaw->SetAlphaFactor(this->rawalpha);
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::ResumeApplication);
|
am::MenuCommandWriter writer(am::DaemonMessage::ResumeApplication);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
am::MenuCommandResultReader reader;
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -801,7 +811,7 @@ namespace ui
|
||||||
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "suspended_app"), cfg::GetLanguageString(config.main_lang, config.default_lang, "suspended_close"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
|
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "suspended_app"), cfg::GetLanguageString(config.main_lang, config.default_lang, "suspended_close"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
|
||||||
if(sopt == 0)
|
if(sopt == 0)
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::TerminateApplication);
|
am::MenuCommandWriter writer(am::DaemonMessage::TerminateApplication);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
this->itemsMenu->UnsetSuspendedItem();
|
this->itemsMenu->UnsetSuspendedItem();
|
||||||
|
@ -828,7 +838,7 @@ namespace ui
|
||||||
strcpy(ipt.nro_argv, rec.nro_target.nro_argv);
|
strcpy(ipt.nro_argv, rec.nro_target.nro_argv);
|
||||||
if(strlen(rec.nro_target.nro_argv)) sprintf(ipt.nro_argv, "%s %s", rec.nro_target.nro_path, rec.nro_target.nro_argv);
|
if(strlen(rec.nro_target.nro_argv)) sprintf(ipt.nro_argv, "%s %s", rec.nro_target.nro_path, rec.nro_target.nro_argv);
|
||||||
|
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::LaunchHomebrewLibApplet);
|
am::MenuCommandWriter writer(am::DaemonMessage::LaunchHomebrewLibraryApplet);
|
||||||
writer.Write<hb::HbTargetParams>(ipt);
|
writer.Write<hb::HbTargetParams>(ipt);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
|
@ -838,38 +848,46 @@ namespace ui
|
||||||
}
|
}
|
||||||
else if(launchmode == 2)
|
else if(launchmode == 2)
|
||||||
{
|
{
|
||||||
bool launch = true;
|
if(config.homebrew_title_application_id != 0)
|
||||||
if(qapp->IsSuspended())
|
|
||||||
{
|
{
|
||||||
launch = false;
|
bool launch = true;
|
||||||
this->HandleCloseSuspended();
|
if(qapp->IsSuspended())
|
||||||
if(!qapp->IsSuspended()) launch = true;
|
{
|
||||||
|
launch = false;
|
||||||
|
this->HandleCloseSuspended();
|
||||||
|
if(!qapp->IsSuspended()) launch = true;
|
||||||
|
}
|
||||||
|
if(launch)
|
||||||
|
{
|
||||||
|
pu::audio::Play(this->sfxTitleLaunch);
|
||||||
|
hb::HbTargetParams ipt = {};
|
||||||
|
strcpy(ipt.nro_path, rec.nro_target.nro_path);
|
||||||
|
strcpy(ipt.nro_argv, rec.nro_target.nro_argv);
|
||||||
|
if(strlen(rec.nro_target.nro_argv)) sprintf(ipt.nro_argv, "%s %s", rec.nro_target.nro_path, rec.nro_target.nro_argv);
|
||||||
|
|
||||||
|
am::MenuCommandWriter writer(am::DaemonMessage::LaunchHomebrewApplication);
|
||||||
|
writer.Write<u64>(config.homebrew_title_application_id);
|
||||||
|
writer.Write<hb::HbTargetParams>(ipt);
|
||||||
|
writer.FinishWrite();
|
||||||
|
|
||||||
|
am::MenuCommandResultReader reader;
|
||||||
|
if(reader && R_SUCCEEDED(reader.GetReadResult()))
|
||||||
|
{
|
||||||
|
qapp->StopPlayBGM();
|
||||||
|
qapp->CloseWithFadeOut();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto rc = reader.GetReadResult();
|
||||||
|
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "app_launch_error") + ": " + util::FormatResult(rc));
|
||||||
|
}
|
||||||
|
reader.FinishRead();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(launch)
|
else
|
||||||
{
|
{
|
||||||
pu::audio::Play(this->sfxTitleLaunch);
|
qapp->CreateShowDialog("Launch", "There is no title specified for homebrew to take over it.\nSelect one by pressing up over it.", { "Ok" }, true);
|
||||||
hb::HbTargetParams ipt = {};
|
|
||||||
strcpy(ipt.nro_path, rec.nro_target.nro_path);
|
|
||||||
strcpy(ipt.nro_argv, rec.nro_target.nro_argv);
|
|
||||||
if(strlen(rec.nro_target.nro_argv)) sprintf(ipt.nro_argv, "%s %s", rec.nro_target.nro_path, rec.nro_target.nro_argv);
|
|
||||||
|
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::LaunchHomebrewApplication);
|
|
||||||
writer.Write<hb::HbTargetParams>(ipt);
|
|
||||||
writer.FinishWrite();
|
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
|
||||||
if(reader && R_SUCCEEDED(reader.GetReadResult()))
|
|
||||||
{
|
|
||||||
qapp->StopPlayBGM();
|
|
||||||
qapp->CloseWithFadeOut();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto rc = reader.GetReadResult();
|
|
||||||
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "app_launch_error") + ": " + util::FormatResult(rc));
|
|
||||||
}
|
|
||||||
reader.FinishRead();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -878,11 +896,11 @@ namespace ui
|
||||||
{
|
{
|
||||||
auto uid = qapp->GetSelectedUser();
|
auto uid = qapp->GetSelectedUser();
|
||||||
|
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::UserHasPassword);
|
am::MenuCommandWriter writer(am::DaemonMessage::UserHasPassword);
|
||||||
writer.Write<AccountUid>(uid);
|
writer.Write<AccountUid>(uid);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader res;
|
am::MenuCommandResultReader res;
|
||||||
res.FinishRead();
|
res.FinishRead();
|
||||||
|
|
||||||
bool has_pass = R_SUCCEEDED(res.GetReadResult());
|
bool has_pass = R_SUCCEEDED(res.GetReadResult());
|
||||||
|
@ -929,12 +947,12 @@ namespace ui
|
||||||
rc = rc3;
|
rc = rc3;
|
||||||
if(R_SUCCEEDED(rc))
|
if(R_SUCCEEDED(rc))
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::ChangeUserPassword);
|
am::MenuCommandWriter writer(am::DaemonMessage::ChangeUserPassword);
|
||||||
writer.Write<db::PassBlock>(oldpass);
|
writer.Write<db::PassBlock>(oldpass);
|
||||||
writer.Write<db::PassBlock>(newpass);
|
writer.Write<db::PassBlock>(newpass);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
am::MenuCommandResultReader reader;
|
||||||
rc = reader.GetReadResult();
|
rc = reader.GetReadResult();
|
||||||
}
|
}
|
||||||
qapp->ShowNotification(R_SUCCEEDED(rc) ? cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_change_ok") : cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_change_error") + ": " + util::FormatResult(rc));
|
qapp->ShowNotification(R_SUCCEEDED(rc) ? cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_change_ok") : cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_change_error") + ": " + util::FormatResult(rc));
|
||||||
|
@ -946,11 +964,11 @@ namespace ui
|
||||||
auto sopt2 = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_full"), cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
|
auto sopt2 = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_full"), cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
|
||||||
if(sopt2 == 0)
|
if(sopt2 == 0)
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::RemoveUserPassword);
|
am::MenuCommandWriter writer(am::DaemonMessage::RemoveUserPassword);
|
||||||
writer.Write<db::PassBlock>(oldpass);
|
writer.Write<db::PassBlock>(oldpass);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
am::MenuCommandResultReader reader;
|
||||||
rc = reader.GetReadResult();
|
rc = reader.GetReadResult();
|
||||||
|
|
||||||
qapp->ShowNotification(R_SUCCEEDED(rc) ? cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_ok") : cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_error") + ": " + util::FormatResult(rc));
|
qapp->ShowNotification(R_SUCCEEDED(rc) ? cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_ok") : cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_remove_error") + ": " + util::FormatResult(rc));
|
||||||
|
@ -979,11 +997,11 @@ namespace ui
|
||||||
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_reg"), cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_reg_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
|
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_reg"), cfg::GetLanguageString(config.main_lang, config.default_lang, "user_pass_reg_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
|
||||||
if(sopt == 0)
|
if(sopt == 0)
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::RegisterUserPassword);
|
am::MenuCommandWriter writer(am::DaemonMessage::RegisterUserPassword);
|
||||||
writer.Write<db::PassBlock>(newpass);
|
writer.Write<db::PassBlock>(newpass);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
am::MenuCommandResultReader reader;
|
||||||
rc = reader.GetReadResult();
|
rc = reader.GetReadResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -998,9 +1016,9 @@ namespace ui
|
||||||
*(u32*)in = 7; // Type -> ShowMyProfile
|
*(u32*)in = 7; // Type -> ShowMyProfile
|
||||||
memcpy((AccountUid*)(in + 0x8), &uid, sizeof(uid));
|
memcpy((AccountUid*)(in + 0x8), &uid, sizeof(uid));
|
||||||
|
|
||||||
am::LibraryAppletQMenuLaunchWithSimple(AppletId_myPage, 1, in, sizeof(in), NULL, 0, [&]() -> bool
|
am::LibraryAppletDaemonLaunchWithSimple(AppletId_myPage, 1, in, sizeof(in), NULL, 0, [&]() -> bool
|
||||||
{
|
{
|
||||||
return !am::QMenuIsHomePressed();
|
return !am::MenuIsHomePressed();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if(sopt == 2)
|
else if(sopt == 2)
|
||||||
|
@ -1017,7 +1035,7 @@ namespace ui
|
||||||
{
|
{
|
||||||
if(logoff == 2)
|
if(logoff == 2)
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::TerminateApplication);
|
am::MenuCommandWriter writer(am::DaemonMessage::TerminateApplication);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
this->itemsMenu->UnsetSuspendedItem();
|
this->itemsMenu->UnsetSuspendedItem();
|
||||||
|
@ -1046,7 +1064,7 @@ namespace ui
|
||||||
webPageCreate(&web, url);
|
webPageCreate(&web, url);
|
||||||
webConfigSetWhitelist(&web, ".*");
|
webConfigSetWhitelist(&web, ".*");
|
||||||
|
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::OpenWebPage);
|
am::MenuCommandWriter writer(am::DaemonMessage::OpenWebPage);
|
||||||
writer.Write<WebCommonConfig>(web);
|
writer.Write<WebCommonConfig>(web);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
|
@ -1086,7 +1104,7 @@ namespace ui
|
||||||
arg2.take_over_connection = true;
|
arg2.take_over_connection = true;
|
||||||
arg2.left_justify = true;
|
arg2.left_justify = true;
|
||||||
|
|
||||||
am::LibraryAppletQMenuLaunchWith(AppletId_controller, 0,
|
am::LibraryAppletDaemonLaunchWith(AppletId_controller, 0,
|
||||||
[&](AppletHolder *h)
|
[&](AppletHolder *h)
|
||||||
{
|
{
|
||||||
libappletPushInData(h, &arg1, sizeof(arg1));
|
libappletPushInData(h, &arg1, sizeof(arg1));
|
||||||
|
@ -1097,7 +1115,7 @@ namespace ui
|
||||||
},
|
},
|
||||||
[&]() -> bool
|
[&]() -> bool
|
||||||
{
|
{
|
||||||
return !am::QMenuIsHomePressed();
|
return !am::MenuIsHomePressed();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,7 +1135,7 @@ namespace ui
|
||||||
|
|
||||||
void MenuLayout::HandleOpenAlbum()
|
void MenuLayout::HandleOpenAlbum()
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::OpenAlbum);
|
am::MenuCommandWriter writer(am::DaemonMessage::OpenAlbum);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
qapp->StopPlayBGM();
|
qapp->StopPlayBGM();
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
#include <os/os_Account.hpp>
|
#include <os/os_Account.hpp>
|
||||||
#include <os/os_Misc.hpp>
|
#include <os/os_Misc.hpp>
|
||||||
#include <util/util_Convert.hpp>
|
#include <util/util_Convert.hpp>
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <fs/fs_Stdio.hpp>
|
#include <fs/fs_Stdio.hpp>
|
||||||
#include <net/net_Service.hpp>
|
#include <net/net_Service.hpp>
|
||||||
#include <am/am_LibraryApplet.hpp>
|
#include <am/am_LibraryApplet.hpp>
|
||||||
|
|
||||||
extern ui::QMenuApplication::Ref qapp;
|
extern ui::MenuApplication::Ref qapp;
|
||||||
extern cfg::Theme theme;
|
extern cfg::Theme theme;
|
||||||
extern cfg::Config config;
|
extern cfg::Config config;
|
||||||
|
|
||||||
|
@ -177,9 +177,9 @@ namespace ui
|
||||||
*(u32*)in = 1; // 0 = normal, 1 = qlaunch, 2 = starter?
|
*(u32*)in = 1; // 0 = normal, 1 = qlaunch, 2 = starter?
|
||||||
u8 out[8] = {0};
|
u8 out[8] = {0};
|
||||||
|
|
||||||
am::LibraryAppletQMenuLaunchWithSimple(AppletId_netConnect, 0, in, sizeof(in), out, sizeof(out), [&]() -> bool
|
am::LibraryAppletDaemonLaunchWithSimple(AppletId_netConnect, 0, in, sizeof(in), out, sizeof(out), [&]() -> bool
|
||||||
{
|
{
|
||||||
return !am::QMenuIsHomePressed();
|
return !am::MenuIsHomePressed();
|
||||||
});
|
});
|
||||||
auto rc = *(u32*)in;
|
auto rc = *(u32*)in;
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ namespace ui
|
||||||
{
|
{
|
||||||
qapp->CommonMenuOnLoop();
|
qapp->CommonMenuOnLoop();
|
||||||
|
|
||||||
bool ret = am::QMenuIsHomePressed();
|
bool ret = am::MenuIsHomePressed();
|
||||||
if(down & KEY_B) ret = true;
|
if(down & KEY_B) ret = true;
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include <ui/ui_StartupLayout.hpp>
|
#include <ui/ui_StartupLayout.hpp>
|
||||||
#include <os/os_Account.hpp>
|
#include <os/os_Account.hpp>
|
||||||
#include <util/util_Convert.hpp>
|
#include <util/util_Convert.hpp>
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <fs/fs_Stdio.hpp>
|
#include <fs/fs_Stdio.hpp>
|
||||||
|
|
||||||
extern ui::QMenuApplication::Ref qapp;
|
extern ui::MenuApplication::Ref qapp;
|
||||||
extern cfg::Theme theme;
|
extern cfg::Theme theme;
|
||||||
extern cfg::Config config;
|
extern cfg::Config config;
|
||||||
|
|
||||||
|
@ -66,11 +66,11 @@ namespace ui
|
||||||
rc = rc2;
|
rc = rc2;
|
||||||
if(R_SUCCEEDED(rc))
|
if(R_SUCCEEDED(rc))
|
||||||
{
|
{
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::TryLogUser);
|
am::MenuCommandWriter writer(am::DaemonMessage::TryLogUser);
|
||||||
writer.Write<db::PassBlock>(pass);
|
writer.Write<db::PassBlock>(pass);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader reader;
|
am::MenuCommandResultReader reader;
|
||||||
rc = reader.GetReadResult();
|
rc = reader.GetReadResult();
|
||||||
reader.FinishRead();
|
reader.FinishRead();
|
||||||
|
|
||||||
|
@ -119,11 +119,11 @@ namespace ui
|
||||||
auto [rc, name] = os::GetAccountName(user);
|
auto [rc, name] = os::GetAccountName(user);
|
||||||
if(R_FAILED(rc)) continue;
|
if(R_FAILED(rc)) continue;
|
||||||
|
|
||||||
am::QMenuCommandWriter writer(am::QDaemonMessage::UserHasPassword);
|
am::MenuCommandWriter writer(am::DaemonMessage::UserHasPassword);
|
||||||
writer.Write<AccountUid>(user);
|
writer.Write<AccountUid>(user);
|
||||||
writer.FinishWrite();
|
writer.FinishWrite();
|
||||||
|
|
||||||
am::QMenuCommandResultReader res;
|
am::MenuCommandResultReader res;
|
||||||
res.FinishRead();
|
res.FinishRead();
|
||||||
|
|
||||||
bool has_pass = R_SUCCEEDED(res.GetReadResult());
|
bool has_pass = R_SUCCEEDED(res.GetReadResult());
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include <ui/ui_ThemeMenuLayout.hpp>
|
#include <ui/ui_ThemeMenuLayout.hpp>
|
||||||
#include <os/os_Account.hpp>
|
#include <os/os_Account.hpp>
|
||||||
#include <util/util_Convert.hpp>
|
#include <util/util_Convert.hpp>
|
||||||
#include <ui/ui_QMenuApplication.hpp>
|
#include <ui/ui_MenuApplication.hpp>
|
||||||
#include <fs/fs_Stdio.hpp>
|
#include <fs/fs_Stdio.hpp>
|
||||||
|
|
||||||
extern ui::QMenuApplication::Ref qapp;
|
extern ui::MenuApplication::Ref qapp;
|
||||||
extern cfg::Theme theme;
|
extern cfg::Theme theme;
|
||||||
extern cfg::Config config;
|
extern cfg::Config config;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ namespace ui
|
||||||
|
|
||||||
void ThemeMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
|
void ThemeMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
|
||||||
{
|
{
|
||||||
bool ret = am::QMenuIsHomePressed();
|
bool ret = am::MenuIsHomePressed();
|
||||||
if(down & KEY_B) ret = true;
|
if(down & KEY_B) ret = true;
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue