Some cleanup, small fixes, ECS working fine now

This commit is contained in:
XorTroll 2020-02-04 19:01:59 +01:00
parent f086264fb5
commit aa492d8fe3
36 changed files with 697 additions and 697 deletions

View file

@ -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!

View file

@ -1,6 +1,6 @@
# 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

@ -1 +1 @@
Subproject commit e5c501e5b66fbeeb57cbc03856582ad470084aca
Subproject commit b83ddf8157e7aef37159aaff9e0b40b137339504

View file

@ -2,57 +2,15 @@
#pragma once
#include <stratosphere.hpp>
#include <ul_Include.hpp>
#include <am/am_Application.hpp>
#include <algorithm>
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();
void Exit();
Result RegisterExternalContent(u64 program_id, std::string exefs_path);
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);
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)
{
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;
}

View file

@ -9,13 +9,14 @@
#include <am/am_Application.hpp>
#include <am/am_LibraryApplet.hpp>
#include <am/am_HomeMenu.hpp>
#include <am/am_QCommunications.hpp>
#include <am/am_DaemonMenuInteraction.hpp>
#include <util/util_Convert.hpp>
#include <cfg/cfg_Config.hpp>
extern "C"
{
u32 __nx_applet_type = AppletType_SystemApplet;
TimeServiceType __nx_time_service_type = TimeServiceType_System;
#if UL_DEV
size_t __nx_heap_size = 0x3000000; // Dev builds use 48MB (still lower than official qlaunch) for debug console
#else
@ -35,11 +36,12 @@ namespace ams
AccountUid selected_uid = {};
hb::HbTargetParams hblaunch_flag = {};
hb::HbTargetParams hbapplaunch_copy = {};
hb::HbTargetParams hbapplaunch_flag = {};
hb::HbTargetParams hbapplaunch_flag_temp = {};
u64 titlelaunch_flag = 0;
WebCommonConfig webapplet_flag = {};
bool album_flag = false;
bool app_opened_hb = false;
u8 *usbbuf = nullptr;
cfg::Config config = {};
Thread ipc_thr;
@ -49,22 +51,22 @@ Thread usb_thr;
bool debug_menu = false;
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));
cfg::TitleType tmptype = cfg::TitleType::Invalid;
if(am::ApplicationIsActive())
{
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();
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;
}
@ -74,20 +76,20 @@ void HandleSleep()
appletStartSleepSequence(true);
}
Result LaunchMenu(am::QMenuStartMode stmode, am::QDaemonStatus status)
Result LaunchMenu(am::MenuStartMode stmode, am::DaemonStatus status)
{
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()
{
bool used_to_reopen_menu = false;
if(am::LibraryAppletIsActive() && !am::LibraryAppletIsQMenu())
if(am::LibraryAppletIsActive() && !am::LibraryAppletIsMenu())
{
am::LibraryAppletTerminate();
auto status = CreateStatus();
UL_R_TRY(LaunchMenu(am::QMenuStartMode::Menu, status));
UL_R_TRY(LaunchMenu(am::MenuStartMode::Menu, status));
return;
}
if(am::ApplicationIsActive())
@ -96,14 +98,14 @@ void HandleHomeButton()
{
am::HomeMenuSetForeground();
auto status = CreateStatus();
UL_R_TRY(LaunchMenu(am::QMenuStartMode::MenuApplicationSuspended, status));
UL_R_TRY(LaunchMenu(am::MenuStartMode::MenuApplicationSuspended, status));
used_to_reopen_menu = true;
}
}
if(am::LibraryAppletIsQMenu() && !used_to_reopen_menu)
if(am::LibraryAppletIsMenu() && !used_to_reopen_menu)
{
std::scoped_lock _lock(latestqlock);
latestqmenumsg = am::QMenuMessage::HomeRequest;
latestqmenumsg = am::MenuMessage::HomeRequest;
}
}
@ -185,162 +187,165 @@ void HandleAppletMessage()
void HandleMenuMessage()
{
if(am::LibraryAppletIsQMenu())
if(am::LibraryAppletIsMenu())
{
am::QDaemonCommandReader reader;
am::DaemonCommandReader reader;
if(reader)
{
switch(reader.GetMessage())
{
case am::QDaemonMessage::SetSelectedUser:
case am::DaemonMessage::SetSelectedUser:
{
selected_uid = reader.Read<AccountUid>();
reader.FinishRead();
break;
}
case am::QDaemonMessage::LaunchApplication:
case am::DaemonMessage::LaunchApplication:
{
auto app_id = reader.Read<u64>();
reader.FinishRead();
if(am::ApplicationIsActive())
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, ApplicationActive));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, ApplicationActive));
res.FinishWrite();
}
else if(!accountUidIsValid(&selected_uid))
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, InvalidSelectedUser));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, InvalidSelectedUser));
res.FinishWrite();
}
else if(titlelaunch_flag > 0)
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, AlreadyQueued));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, AlreadyQueued));
res.FinishWrite();
}
else
{
titlelaunch_flag = app_id;
am::QDaemonCommandResultWriter res(0);
am::DaemonCommandResultWriter res(0);
res.FinishWrite();
}
break;
}
case am::QDaemonMessage::ResumeApplication:
case am::DaemonMessage::ResumeApplication:
{
reader.FinishRead();
if(!am::ApplicationIsActive())
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, ApplicationNotActive));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, ApplicationNotActive));
res.FinishWrite();
}
else
{
am::ApplicationSetForeground();
am::QDaemonCommandResultWriter res(0);
am::DaemonCommandResultWriter res(0);
res.FinishWrite();
}
break;
}
case am::QDaemonMessage::TerminateApplication:
case am::DaemonMessage::TerminateApplication:
{
reader.FinishRead();
am::ApplicationTerminate();
app_opened_hb = false;
break;
}
case am::QDaemonMessage::LaunchHomebrewLibApplet:
case am::DaemonMessage::LaunchHomebrewLibraryApplet:
{
hblaunch_flag = reader.Read<hb::HbTargetParams>();
reader.FinishRead();
break;
}
case am::QDaemonMessage::LaunchHomebrewApplication:
case am::DaemonMessage::LaunchHomebrewApplication:
{
auto app_id = reader.Read<u64>();
auto ipt = reader.Read<hb::HbTargetParams>();
reader.FinishRead();
if(am::ApplicationIsActive())
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, ApplicationActive));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, ApplicationActive));
res.FinishWrite();
}
else if(!accountUidIsValid(&selected_uid))
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, InvalidSelectedUser));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, InvalidSelectedUser));
res.FinishWrite();
}
else if(titlelaunch_flag > 0)
{
am::QDaemonCommandResultWriter res(RES_VALUE(QDaemon, AlreadyQueued));
am::DaemonCommandResultWriter res(RES_VALUE(Daemon, AlreadyQueued));
res.FinishWrite();
}
else
{
hbapplaunch_copy = ipt;
hbapplaunch_flag = hbapplaunch_copy;
am::QDaemonCommandResultWriter res(0);
memcpy(&hbapplaunch_flag, &ipt, sizeof(ipt));
memcpy(&hbapplaunch_flag_temp, &ipt, sizeof(ipt));
titlelaunch_flag = app_id;
am::DaemonCommandResultWriter res(0);
res.FinishWrite();
}
break;
}
case am::QDaemonMessage::OpenWebPage:
case am::DaemonMessage::OpenWebPage:
{
webapplet_flag = reader.Read<WebCommonConfig>();
reader.FinishRead();
break;
}
case am::QDaemonMessage::GetSelectedUser:
case am::DaemonMessage::GetSelectedUser:
{
reader.FinishRead();
am::QDaemonCommandResultWriter res(0);
am::DaemonCommandResultWriter res(0);
res.Write<AccountUid>(selected_uid);
res.FinishWrite();
break;
}
case am::QDaemonMessage::UserHasPassword:
case am::DaemonMessage::UserHasPassword:
{
auto uid = reader.Read<AccountUid>();
reader.FinishRead();
auto [rc, pass] = db::AccessPassword(uid);
am::QDaemonCommandResultWriter res(rc);
am::DaemonCommandResultWriter res(rc);
res.FinishWrite();
break;
}
case am::QDaemonMessage::TryLogUser:
case am::DaemonMessage::TryLogUser:
{
auto pass = reader.Read<db::PassBlock>();
reader.FinishRead();
auto rc = db::TryLogUser(pass);
am::QDaemonCommandResultWriter res(rc);
am::DaemonCommandResultWriter res(rc);
res.FinishWrite();
break;
}
case am::QDaemonMessage::RegisterUserPassword:
case am::DaemonMessage::RegisterUserPassword:
{
auto pass = reader.Read<db::PassBlock>();
reader.FinishRead();
auto rc = db::RegisterUserPassword(pass);
am::QDaemonCommandResultWriter res(rc);
am::DaemonCommandResultWriter res(rc);
res.FinishWrite();
break;
}
case am::QDaemonMessage::ChangeUserPassword:
case am::DaemonMessage::ChangeUserPassword:
{
auto pass = reader.Read<db::PassBlock>();
auto newpass = reader.Read<db::PassBlock>();
@ -353,12 +358,12 @@ void HandleMenuMessage()
if(R_SUCCEEDED(rc)) rc = db::RegisterUserPassword(newpass);
}
am::QDaemonCommandResultWriter res(rc);
am::DaemonCommandResultWriter res(rc);
res.FinishWrite();
break;
}
case am::QDaemonMessage::RemoveUserPassword:
case am::DaemonMessage::RemoveUserPassword:
{
auto pass = reader.Read<db::PassBlock>();
reader.FinishRead();
@ -369,12 +374,12 @@ void HandleMenuMessage()
rc = db::RemoveUserPassword(pass.uid);
}
am::QDaemonCommandResultWriter res(rc);
am::DaemonCommandResultWriter res(rc);
res.FinishWrite();
break;
}
case am::QDaemonMessage::OpenAlbum:
case am::DaemonMessage::OpenAlbum:
{
reader.FinishRead();
album_flag = true;
@ -400,15 +405,15 @@ namespace
constexpr size_t MaxServers = 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;
}
namespace qdaemon
namespace daemn
{
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();
}
@ -435,7 +440,7 @@ namespace qdaemon
{
if(!am::LibraryAppletIsActive())
{
am::WebAppletStart(&webapplet_flag);
UL_R_TRY(am::WebAppletStart(&webapplet_flag));
sth_done = true;
memset(&webapplet_flag, 0, sizeof(webapplet_flag));
@ -446,7 +451,7 @@ namespace qdaemon
if(!am::LibraryAppletIsActive())
{
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;
album_flag = false;
@ -456,18 +461,21 @@ namespace qdaemon
{
if(!am::LibraryAppletIsActive())
{
am::ApplicationStart(titlelaunch_flag, false, selected_uid);
sth_done = true;
titlelaunch_flag = 0;
}
}
if(strlen(hbapplaunch_flag.nro_path))
{
if(!am::LibraryAppletIsActive())
{
am::ApplicationStart(OS_FLOG_APP_ID, true, selected_uid, &hbapplaunch_flag, sizeof(hbapplaunch_flag));
sth_done = true;
hbapplaunch_flag.nro_path[0] = '\0';
if(strlen(hbapplaunch_flag.nro_path))
{
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/", &params, sizeof(params), selected_uid));
sth_done = true;
app_opened_hb = true;
titlelaunch_flag = 0;
hbapplaunch_flag.nro_path[0] = '\0';
}
else
{
UL_R_TRY(am::ApplicationStart(titlelaunch_flag, false, selected_uid));
sth_done = true;
titlelaunch_flag = 0;
}
}
}
if(strlen(hblaunch_flag.nro_path))
@ -475,36 +483,29 @@ namespace qdaemon
if(!am::LibraryAppletIsActive())
{
auto params = hb::HbTargetParams::Create(hblaunch_flag.nro_path, hblaunch_flag.nro_argv, false);
auto rc = ecs::RegisterLaunchAsApplet(0x0100000000001003, 0, "/ulaunch/bin/uHbTarget/applet/", &params, sizeof(params));
UL_R_TRY(ecs::RegisterLaunchAsApplet(config.homebrew_applet_program_id, 0, "/ulaunch/bin/uHbTarget/applet/", &params, sizeof(params)));
sth_done = true;
hblaunch_flag.nro_path[0] = '\0';
}
}
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:
case AppletId_web:
case AppletId_photoViewer:
{
auto status = CreateStatus();
UL_R_TRY(LaunchMenu(am::QMenuStartMode::Menu, status));
sth_done = true;
break;
}
default:
break;
auto status = CreateStatus();
UL_R_TRY(LaunchMenu(am::MenuStartMode::Menu, status));
sth_done = true;
}
}
if(!sth_done && !debug_menu)
{
// 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())
{
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");
config = cfg::EnsureConfig();
am::LibraryAppletSetMenuAppletId(am::LibraryAppletGetAppletIdForProgramId(config.menu_program_id));
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()
{
qdaemon::Initialize();
daemn::Initialize();
// Cache everything on startup
cfg::CacheEverything();
auto status = CreateStatus();
UL_R_TRY(LaunchMenu(am::QMenuStartMode::StartupScreen, status))
UL_R_TRY(LaunchMenu(am::MenuStartMode::StartupScreen, status))
while(true)
{
qdaemon::LoopUpdate();
daemn::LoopUpdate();
svcSleepThread(10'000'000);
}
qdaemon::Exit();
daemn::Exit();
return 0;
}

View file

@ -5,7 +5,7 @@
#include <am/am_Application.hpp>
#include <am/am_LibraryApplet.hpp>
#include <am/am_HomeMenu.hpp>
#include <am/am_QCommunications.hpp>
#include <am/am_DaemonMenuInteraction.hpp>
namespace ecs
{
@ -25,7 +25,7 @@ namespace ecs
ams::sf::hipc::ServerManager<MaxServers, ServerOptions> manager_instance;
}
static void ManagerLoopHandler(void *arg)
static void ECSManagerThread(void *arg)
{
manager_instance.LoopProcess();
}
@ -38,7 +38,7 @@ namespace ecs
initialized = R_SUCCEEDED(rc);
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));
}
return rc;
@ -87,15 +87,10 @@ namespace ecs
Result LaunchApplet(u64 program_id, u32 la_version, void *args, size_t args_size)
{
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);
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)
{

View file

@ -1,8 +1,8 @@
#include <ipc/ipc_IDaemonService.hpp>
#include <am/am_QCommunications.hpp>
#include <am/am_DaemonMenuInteraction.hpp>
extern ams::os::Mutex latestqlock;
extern am::QMenuMessage latestqmenumsg;
extern am::DaemonMessage latestqmenumsg;
namespace ipc
{
@ -10,6 +10,6 @@ namespace ipc
{
std::scoped_lock _lock(latestqlock);
msg.SetValue((u32)latestqmenumsg);
latestqmenumsg = am::QMenuMessage::Invalid;
latestqmenumsg = am::DaemonMessage::Invalid;
}
}

View file

@ -17,11 +17,10 @@ namespace am
static_assert(sizeof(ApplicationSelectedUserArgument) == 0x400, "ApplicationSelectedUserArgument must be 0x400!");
static constexpr u32 SelectedUserMagic = 0xC79497CA;
static constexpr u64 QHbTargetSystemApplicationId = OS_FLOG_APP_ID;
bool ApplicationIsActive();
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();
Result ApplicationSetForeground();
Result ApplicationSend(void *data, size_t size, AppletLaunchParameterKind kind = AppletLaunchParameterKind_UserChannel);

View file

@ -3,9 +3,12 @@
#include <ul_Include.hpp>
#include <hb/hb_Target.hpp>
#define AM_DAEMON_PRIVATE_SERVICE_NAME "qdmnsrv"
#define AM_DAEMON_PUBLIC_SERVICE_NAME "ulaunch"
namespace am
{
enum class QMenuStartMode
enum class MenuStartMode
{
Invalid,
StartupScreen,
@ -14,20 +17,20 @@ namespace am
MenuLaunchFailure
};
enum class QMenuMessage
enum class MenuMessage
{
Invalid,
HomeRequest
};
enum class QDaemonMessage
enum class DaemonMessage
{
Invalid,
SetSelectedUser,
LaunchApplication,
ResumeApplication,
TerminateApplication,
LaunchHomebrewLibApplet,
LaunchHomebrewLibraryApplet,
LaunchHomebrewApplication,
OpenWebPage,
GetSelectedUser,
@ -39,36 +42,29 @@ namespace am
OpenAlbum,
};
struct QDaemonStatus
struct DaemonStatus
{
AccountUid selected_user;
hb::HbTargetParams params; // Set if homebrew (via flog takeover) 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 QDaemon_LaunchQHbTarget(hb::HbTargetParams input);
Result Menu_InitializeDaemonService();
ResultWith<MenuMessage> Menu_GetLatestMenuMessage();
bool MenuIsHomePressed();
void Menu_FinalizeDaemonService();
Result QLibraryAppletReadStorage(void *data, size_t size);
Result QApplicationReadStorage(void *data, size_t size);
ResultWith<QMenuStartMode> QMenu_ProcessInput();
Result Daemon_MenuWriteImpl(void *data, size_t size, bool wait);
Result Daemon_MenuReadImpl(void *data, size_t size, bool wait);
Result QMenu_InitializeDaemonService();
ResultWith<QMenuMessage> QMenu_GetLatestQMenuMessage();
bool QMenuIsHomePressed();
void QMenu_FinalizeDaemonService();
Result Menu_DaemonWriteImpl(void *data, size_t size, bool wait);
Result Menu_DaemonReadImpl(void *data, size_t size, bool wait);
Result QDaemon_QMenuWriteImpl(void *data, size_t size, bool wait);
Result QDaemon_QMenuReadImpl(void *data, size_t size, bool wait);
typedef Result(*DMCommandRWFunction)(void*, size_t, bool);
Result QMenu_QDaemonWriteImpl(void *data, size_t size, bool wait);
Result QMenu_QDaemonReadImpl(void *data, size_t size, bool wait);
typedef Result(*QCommandRWFunction)(void*, size_t, bool);
struct QCommandCommonHeader
struct DMCommandCommonHeader
{
u32 magic;
u32 val;
@ -77,18 +73,18 @@ namespace am
static constexpr u32 Magic = 0x434D4151;
static constexpr size_t BlockSize = 0x4000;
template<QCommandRWFunction WriteFn>
class QCommandWriter
template<DMCommandRWFunction WriteFn>
class DMCommandWriter
{
private:
QCommandCommonHeader request;
DMCommandCommonHeader request;
u8 *data_block;
size_t data_pos;
Result inner_rc;
bool write_done;
public:
QCommandWriter(u32 value)
DMCommandWriter(u32 value)
{
write_done = false;
request.magic = Magic;
@ -98,7 +94,7 @@ namespace am
inner_rc = WriteFn(&request, sizeof(request), false);
}
~QCommandWriter()
~DMCommandWriter()
{
FinishWrite();
}
@ -131,11 +127,11 @@ namespace am
}
};
template<QCommandRWFunction ReadFn>
class QCommandReader
template<DMCommandRWFunction ReadFn>
class DMCommandReader
{
private:
QCommandCommonHeader response;
DMCommandCommonHeader response;
u8 *data_block;
size_t data_pos;
Result inner_rc;
@ -143,17 +139,17 @@ namespace am
bool fn_wait;
public:
QCommandReader(bool wait = false)
DMCommandReader(bool wait = false)
{
fn_wait = wait;
read_done = false;
data_pos = 0;
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);
}
~QCommandReader()
~DMCommandReader()
{
FinishRead();
}
@ -191,27 +187,27 @@ namespace am
}
};
class QDaemonCommandReader : public QCommandReader<QDaemon_QMenuReadImpl>
class DaemonCommandReader : public DMCommandReader<Daemon_MenuReadImpl>
{
public:
QDaemonMessage GetMessage()
DaemonMessage GetMessage()
{
return (QDaemonMessage)GetValue();
return (DaemonMessage)GetValue();
}
};
class QDaemonCommandWriter : public QCommandWriter<QDaemon_QMenuWriteImpl>
class DaemonCommandWriter : public DMCommandWriter<Daemon_MenuWriteImpl>
{
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:
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:
QDaemonCommandResultWriter(Result rc) : QCommandWriter(rc)
DaemonCommandResultWriter(Result rc) : DMCommandWriter(rc)
{
}
};
class QMenuCommandReader : public QCommandReader<QMenu_QDaemonReadImpl>
class MenuCommandReader : public DMCommandReader<Menu_DaemonReadImpl>
{
public:
QMenuMessage GetMessage()
MenuMessage GetMessage()
{
return (QMenuMessage)GetValue();
return (MenuMessage)GetValue();
}
};
class QMenuCommandWriter : public QCommandWriter<QMenu_QDaemonWriteImpl>
class MenuCommandWriter : public DMCommandWriter<Menu_DaemonWriteImpl>
{
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:
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:
QMenuCommandResultWriter(Result rc) : QCommandWriter(rc)
MenuCommandResultWriter(Result rc) : DMCommandWriter(rc)
{
}
};

View file

@ -1,6 +1,7 @@
#pragma once
#include <ul_Include.hpp>
#include <map>
namespace am
{
@ -33,29 +34,32 @@ namespace am
}
bool LibraryAppletIsActive();
bool LibraryAppletIsQMenu();
void LibraryAppletSetMenuAppletId(AppletId id);
bool LibraryAppletIsMenu();
void LibraryAppletTerminate();
Result LibraryAppletStart(AppletId id, u32 la_version, void *in_data, size_t in_size);
Result LibraryAppletSend(void *data, size_t size);
Result LibraryAppletRead(void *data, size_t size);
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)
{
if(in_size > 0) libappletPushInData(h, in_data, in_size);
},
[&](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);
}
u64 LibraryAppletGetProgramIdForAppletId(AppletId id);
AppletId LibraryAppletGetAppletIdForProgramId(u64 id);
AppletId LibraryAppletGetId();
static constexpr AppletId QMenuAppletId = AppletId_shop;
static constexpr AppletId QHbTargetAppletId = AppletId_auth;
static constexpr AppletId InvalidAppletId = (AppletId)0;
}

View file

@ -69,14 +69,25 @@ namespace cfg
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
{
std::string theme_name;
bool system_title_override_enabled;
bool viewer_usb_enabled;
u64 menu_program_id;
u64 homebrew_applet_program_id;
u64 homebrew_title_application_id;
JSON main_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;
@ -86,35 +97,35 @@ namespace cfg
#define CFG_CONFIG_JSON UL_BASE_SD_DIR "/config.json"
TitleList LoadTitleList();
std::vector<TitleRecord> QueryAllHomebrew(std::string base = "sdmc:/switch");
void CacheEverything(std::string hb_base_path = "sdmc:/switch");
std::vector<TitleRecord> QueryAllHomebrew(const std::string &base = "sdmc:/switch");
void CacheEverything(const std::string &hb_base_path = "sdmc:/switch");
std::string GetRecordIconPath(TitleRecord record);
RecordInformation GetRecordInformation(TitleRecord record);
Theme LoadTheme(std::string base_name);
Theme LoadTheme(const std::string &base_name);
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();
}
std::string GetLanguageJSONPath(std::string lang);
std::string GetLanguageString(JSON &lang, JSON &def, std::string name);
std::string GetLanguageJSONPath(const std::string &lang);
std::string GetLanguageString(const JSON &lang, const JSON &def, const std::string &name);
Config CreateNewAndLoadConfig();
Config LoadConfig();
Config EnsureConfig();
void SaveConfig(Config &cfg);
void SaveConfig(const Config &cfg);
void SaveRecord(TitleRecord &record);
void RemoveRecord(TitleRecord &record);
bool MoveRecordTo(TitleList &list, TitleRecord record, std::string folder);
TitleFolder &FindFolderByName(TitleList &list, std::string name);
void RenameFolder(TitleList &list, std::string old_name, std::string new_name);
bool MoveRecordTo(TitleList &list, TitleRecord record, const std::string &folder);
TitleFolder &FindFolderByName(TitleList &list, const std::string &name);
void RenameFolder(TitleList &list, const std::string &old_name, const std::string &new_name);
bool ExistsRecord(TitleList &list, TitleRecord record);
std::string GetTitleCacheIconPath(u64 app_id);
std::string GetNROCacheIconPath(std::string path);
std::string GetNROCacheIconPath(const std::string &path);
}

View file

@ -18,7 +18,7 @@ namespace db
void Unmount();
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);
std::string GetUserPasswordFilePath(AccountUid user_id);
Result RegisterUserPassword(PassBlock password);

View file

@ -4,17 +4,17 @@
namespace fs
{
bool ExistsFile(std::string path);
bool ExistsDirectory(std::string path);
bool ExistsFile(const std::string &path);
bool ExistsDirectory(const std::string &path);
void CreateDirectory(std::string path);
void CreateFile(std::string path);
void CreateConcatenationFile(std::string path);
void CreateDirectory(const std::string &path);
void CreateFile(const std::string &path);
void CreateConcatenationFile(const std::string &path);
void DeleteDirectory(std::string path);
void DeleteFile(std::string path);
void DeleteDirectory(const 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+");
if(f)
@ -26,7 +26,7 @@ namespace fs
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");
if(f)
@ -38,7 +38,7 @@ namespace fs
return false;
}
inline size_t GetFileSize(std::string path)
inline size_t GetFileSize(const std::string &path)
{
FILE *f = fopen(path.c_str(), "rb");
if(f)
@ -52,11 +52,11 @@ namespace fs
return 0;
}
void MoveFile(std::string p1, std::string p2);
void CopyFile(std::string p, std::string np);
void MoveFile(const std::string &p1, const std::string &p2);
void CopyFile(const std::string &p, const std::string &np);
void MoveDirectory(std::string d, std::string nd);
void CopyDirectory(std::string d, std::string nd);
void MoveDirectory(const std::string &d, const std::string &nd);
void CopyDirectory(const std::string &d, const std::string &nd);
#define FS_FOR(dir, name_var, path_var, ...) \
DIR *dp = opendir(dir.c_str()); \

View file

@ -38,7 +38,7 @@ namespace hb
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 = {};
params.magic = UL_HB_HBTARGET_MAGIC_U32;

View file

@ -89,14 +89,4 @@ inline void Panic(std::string msg)
// TODO: non-console panic...?
}
inline void HandleECSMain()
{
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); } }
#define UL_R_TRY(expr) { auto _tmp_rc = (expr); if(R_FAILED(_tmp_rc)) { fatalThrow(_tmp_rc); } }

View file

@ -51,7 +51,7 @@ namespace res
RES_DEFINE(InvalidJSONFile, 1)
RES_MODULE_END
RES_MODULE_BEGIN(QDaemon, 3)
RES_MODULE_BEGIN(Daemon, 3)
RES_DEFINE(ApplicationActive, 1)
RES_DEFINE(InvalidSelectedUser, 2)
RES_DEFINE(AlreadyQueued, 3)

View file

@ -5,7 +5,12 @@
namespace util
{
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 FormatResultDisplay(Result rc);
std::string FormatResultHex(Result rc);

View file

@ -4,7 +4,7 @@
namespace util
{
ResultWith<JSON> LoadJSONFromFile(std::string path);
ResultWith<JSON> LoadJSONFromFile(const std::string &path);
std::string GetCurrentTime();
u32 GetBatteryLevel();
bool IsCharging();

View file

@ -4,7 +4,7 @@
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;
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());

View 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);
}
)
}

View file

@ -2,8 +2,30 @@
namespace am
{
AppletHolder applet_holder;
AppletId applet_lastid;
static AppletHolder applet_holder;
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()
{
@ -12,9 +34,14 @@ namespace am
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()
@ -55,7 +82,7 @@ namespace am
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();
appletHolderClose(&applet_holder);
@ -73,17 +100,35 @@ namespace am
LibraryAppletTerminate();
break;
}
svcSleepThread(10'000'000);
svcSleepThread(10'000'000l);
}
on_finish(&applet_holder);
appletHolderClose(&applet_holder);
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()
{
auto idcopy = applet_lastid;
if(!LibraryAppletIsActive()) applet_lastid = (AppletId)0; // Invalid
if(!LibraryAppletIsActive()) applet_lastid = InvalidAppletId;
return idcopy;
}
}

View file

@ -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);
}
)
}

View file

@ -8,7 +8,7 @@
namespace cfg
{
void CacheHomebrew(std::string nro_path)
void CacheHomebrew(const std::string &nro_path)
{
auto nroimg = GetNROCacheIconPath(nro_path);
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;
@ -88,7 +88,7 @@ namespace cfg
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,
{
@ -103,7 +103,7 @@ namespace cfg
})
}
void CacheEverything(std::string hb_base_path)
void CacheEverything(const std::string &hb_base_path)
{
CacheInstalledTitles();
CacheAllHomebrew(hb_base_path);
@ -188,7 +188,7 @@ namespace cfg
return info;
}
Theme LoadTheme(std::string base_name)
Theme LoadTheme(const std::string &base_name)
{
Theme theme = {};
theme.base_name = base_name;
@ -223,7 +223,7 @@ namespace cfg
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;
if(fs::ExistsFile(base_res)) return base_res;
@ -232,12 +232,12 @@ namespace cfg
return "";
}
std::string GetLanguageJSONPath(std::string lang)
std::string GetLanguageJSONPath(const std::string &lang)
{
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, "");
if(str.empty()) str = def.value(name, "");
@ -246,29 +246,36 @@ namespace cfg
Config CreateNewAndLoadConfig()
{
Config cfg = {};
cfg.system_title_override_enabled = false; // Due to ban risk, have it disabled by default.
cfg.viewer_usb_enabled = false; // Do not enable this by default due to conflicts with USB homebrew
cfg.theme_name = ""; // Default theme (none)
// Default constructor sets everything
Config cfg;
SaveConfig(cfg);
return cfg;
}
Config LoadConfig()
{
Config cfg = {};
// Default constructor sets everything
Config cfg;
auto [rc, cfgjson] = util::LoadJSONFromFile(CFG_CONFIG_JSON);
if(R_SUCCEEDED(rc))
{
cfg.theme_name = cfgjson.value("theme_name", "");
cfg.system_title_override_enabled = cfgjson.value("system_title_override_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
{
fs::DeleteFile(CFG_CONFIG_JSON);
return CreateNewAndLoadConfig();
}
// Doing this saves any fields not set previously
SaveConfig(cfg);
return cfg;
}
@ -278,13 +285,15 @@ namespace cfg
return LoadConfig();
}
void SaveConfig(Config &cfg)
void SaveConfig(const Config &cfg)
{
fs::DeleteFile(CFG_CONFIG_JSON);
JSON j = JSON::object();
j["theme_name"] = cfg.theme_name;
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);
ofs << std::setw(4) << j;
ofs.close();
@ -353,7 +362,7 @@ namespace cfg
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;
TitleRecord record_copy = {};
@ -421,7 +430,7 @@ namespace cfg
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;
TitleRecord record_copy = {};
@ -518,7 +527,7 @@ namespace cfg
return title_found;
}
TitleFolder &FindFolderByName(TitleList &list, std::string name)
TitleFolder &FindFolderByName(TitleList &list, const std::string &name)
{
if(!name.empty())
{
@ -531,7 +540,7 @@ namespace cfg
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);
if(!folder.name.empty())
@ -706,7 +715,7 @@ namespace cfg
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};
strcpy(pathcopy, path.c_str());

View file

@ -27,7 +27,7 @@ namespace db
fsdevCommitDevice(UL_DB_MOUNT_NAME);
}
ResultWith<PassBlock> PackPassword(AccountUid uid, std::string pass)
ResultWith<PassBlock> PackPassword(AccountUid uid, const std::string &pass)
{
PassBlock pb = {};
if((pass.length() > 15) || (pass.empty())) return MakeResultWith(RES_VALUE(Db, InvalidPasswordLength), pb);

View file

@ -3,53 +3,53 @@
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;
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);
}
bool ExistsDirectory(std::string path)
bool ExistsDirectory(const std::string &path)
{
return ExistsImpl(S_IFDIR, path);
}
void CreateDirectory(std::string path)
void CreateDirectory(const std::string &path)
{
mkdir(path.c_str(), 777);
}
void CreateFile(std::string path)
void CreateFile(const std::string &path)
{
fsdevCreateFile(path.c_str(), 0, 0);
}
void CreateConcatenationFile(std::string path)
void CreateConcatenationFile(const std::string &path)
{
fsdevCreateFile(path.c_str(), 0, FsCreateOption_BigFile);
}
void DeleteDirectory(std::string path)
void DeleteDirectory(const std::string &path)
{
fsdevDeleteDirectoryRecursively(path.c_str());
}
void DeleteFile(std::string path)
void DeleteFile(const std::string &path)
{
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());
}
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");
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());
CreateDirectory(nd);
@ -102,12 +102,12 @@ namespace fs
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);
}
void CopyDirectory(std::string d, std::string nd)
void CopyDirectory(const std::string &d, const std::string &nd)
{
return HandleDirectoryImpl(true, d, nd);
}

View file

@ -31,11 +31,6 @@ namespace util
return strm.str();
}
u64 Get64FromString(std::string val)
{
return strtoull(val.c_str(), NULL, 16);
}
std::string FormatApplicationId(u64 app_id)
{
std::stringstream strm;

View file

@ -3,7 +3,7 @@
namespace util
{
ResultWith<JSON> LoadJSONFromFile(std::string path)
ResultWith<JSON> LoadJSONFromFile(const std::string &path)
{
JSON ret = JSON::object();
if(fs::ExistsFile(path))

View file

@ -8,16 +8,16 @@
namespace ui
{
class QMenuApplication : public pu::ui::Application
class MenuApplication : public pu::ui::Application
{
public:
using Application::Application;
~QMenuApplication();
PU_SMART_CTOR(QMenuApplication)
~MenuApplication();
PU_SMART_CTOR(MenuApplication)
void OnLoad() override;
void SetInformation(am::QMenuStartMode mode, am::QDaemonStatus status);
void SetInformation(am::MenuStartMode mode, am::DaemonStatus status);
void LoadMenu();
void LoadStartupMenu();
void LoadThemeMenu();
@ -81,14 +81,14 @@ namespace ui
void CommonMenuOnLoop();
private:
am::QMenuStartMode stmode;
am::MenuStartMode stmode;
StartupLayout::Ref startupLayout;
MenuLayout::Ref menuLayout;
ThemeMenuLayout::Ref themeMenuLayout;
SettingsMenuLayout::Ref settingsMenuLayout;
LanguagesMenuLayout::Ref languagesMenuLayout;
pu::ui::extras::Toast::Ref notifToast;
am::QDaemonStatus status;
am::DaemonStatus status;
JSON uijson;
JSON bgmjson;
bool bgm_loop;
@ -97,7 +97,7 @@ namespace ui
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();
}

View file

@ -1,7 +1,7 @@
#pragma once
#include <ul_Include.hpp>
#include <am/am_QCommunications.hpp>
#include <am/am_DaemonMenuInteraction.hpp>
#include <db/db_Save.hpp>
#include <pu/Plutonium>

View file

@ -8,13 +8,15 @@
#include <cfg/cfg_Config.hpp>
#include <net/net_Service.hpp>
#include <util/util_Misc.hpp>
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <os/os_HomeMenu.hpp>
#include <util/util_Convert.hpp>
#include <am/am_LibraryApplet.hpp>
extern "C"
{
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
}
@ -22,7 +24,7 @@ extern "C"
// Some global vars
ui::QMenuApplication::Ref qapp;
ui::MenuApplication::Ref qapp;
cfg::TitleList list;
std::vector<cfg::TitleRecord> homebrew;
cfg::Config config;
@ -40,7 +42,7 @@ namespace qmenu
UL_R_TRY(setsysInitialize())
UL_R_TRY(setInitialize())
UL_R_TRY(am::QMenu_InitializeDaemonService())
UL_R_TRY(am::Menu_InitializeDaemonService())
// Load menu config and theme
config = cfg::EnsureConfig();
@ -49,7 +51,7 @@ namespace qmenu
void Exit()
{
am::QMenu_FinalizeDaemonService();
am::Menu_FinalizeDaemonService();
setExit();
setsysExit();
@ -62,17 +64,17 @@ namespace qmenu
int main()
{
auto [rc, smode] = am::QMenu_ProcessInput();
auto [rc, smode] = am::Menu_ProcessInput();
if(R_SUCCEEDED(rc))
{
am::QDaemonStatus status = {};
am::DaemonStatus status = {};
// Information block sent as an extra storage to QMenu.
am::QLibraryAppletReadStorage(&status, sizeof(status));
// Information block sent as an extra storage to Menu.
am::Menu_DaemonReadImpl(&status, sizeof(status), false);
// 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...
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
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->Prepare();
if(smode == am::QMenuStartMode::MenuApplicationSuspended) qapp->Show();
if(smode == am::MenuStartMode::MenuApplicationSuspended) qapp->Show();
else qapp->ShowWithFadeIn();
// Exit RomFs manually, Plutonium won't do it for us since we're initializing it manually

View file

@ -1,14 +1,14 @@
#include <ui/ui_LanguagesMenuLayout.hpp>
#include <os/os_Account.hpp>
#include <util/util_Convert.hpp>
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <fs/fs_Stdio.hpp>
#include <os/os_Misc.hpp>
#include <os/os_HomeMenu.hpp>
#include <net/net_Service.hpp>
#include <am/am_LibraryApplet.hpp>
extern ui::QMenuApplication::Ref qapp;
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
@ -98,7 +98,7 @@ namespace ui
{
qapp->CommonMenuOnLoop();
bool ret = am::QMenuIsHomePressed();
bool ret = am::MenuIsHomePressed();
if(down & KEY_B)
{
qapp->FadeOut();

View file

@ -1,4 +1,4 @@
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <util/util_Misc.hpp>
extern u8 *app_buf;
@ -6,12 +6,12 @@ extern cfg::Theme theme;
namespace ui
{
QMenuApplication::~QMenuApplication()
MenuApplication::~MenuApplication()
{
pu::audio::Delete(this->bgm);
}
void QMenuApplication::OnLoad()
void MenuApplication::OnLoad()
{
pu::ui::render::SetDefaultFont(cfg::GetAssetByTheme(theme, "ui/Font.ttf"));
@ -43,7 +43,7 @@ namespace ui
switch(this->stmode)
{
case am::QMenuStartMode::StartupScreen:
case am::MenuStartMode::StartupScreen:
this->LoadStartupMenu();
break;
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->status = status;
}
void QMenuApplication::LoadMenu()
void MenuApplication::LoadMenu()
{
this->menuLayout->SetUser(this->status.selected_user);
this->LoadLayout(this->menuLayout);
}
void QMenuApplication::LoadStartupMenu()
void MenuApplication::LoadStartupMenu()
{
this->StopPlayBGM();
this->startupLayout->ReloadMenu();
this->LoadLayout(this->startupLayout);
}
void QMenuApplication::LoadThemeMenu()
void MenuApplication::LoadThemeMenu()
{
this->themeMenuLayout->Reload();
this->LoadLayout(this->themeMenuLayout);
}
void QMenuApplication::LoadSettingsMenu()
void MenuApplication::LoadSettingsMenu()
{
this->settingsMenuLayout->Reload();
this->LoadLayout(this->settingsMenuLayout);
}
void QMenuApplication::LoadSettingsLanguagesMenu()
void MenuApplication::LoadSettingsLanguagesMenu()
{
this->languagesMenuLayout->Reload();
this->LoadLayout(this->languagesMenuLayout);
}
bool QMenuApplication::IsSuspended()
bool MenuApplication::IsSuspended()
{
return this->IsTitleSuspended() || this->IsHomebrewSuspended();
}
bool QMenuApplication::IsTitleSuspended()
bool MenuApplication::IsTitleSuspended()
{
return this->status.app_id > 0;
}
bool QMenuApplication::IsHomebrewSuspended()
bool MenuApplication::IsHomebrewSuspended()
{
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;
}
u64 QMenuApplication::GetSuspendedApplicationId()
u64 MenuApplication::GetSuspendedApplicationId()
{
return this->status.app_id;
}
void QMenuApplication::NotifyEndSuspended()
void MenuApplication::NotifyEndSuspended()
{
// Blanking the whole status would also blank the selected user...
this->status.params = {};
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->notifToast->SetText(text);
this->StartOverlayWithTimeout(this->notifToast, timeout);
}
void QMenuApplication::StartPlayBGM()
void MenuApplication::StartPlayBGM()
{
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);
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.FinishWrite();
memcpy(&this->status.selected_user, &user_id, sizeof(user_id));
}
AccountUid QMenuApplication::GetSelectedUser()
AccountUid MenuApplication::GetSelectedUser()
{
return this->status.selected_user;
}

View file

@ -5,12 +5,12 @@
#include <util/util_Misc.hpp>
#include <os/os_Misc.hpp>
#include <am/am_LibraryApplet.hpp>
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <os/os_HomeMenu.hpp>
#include <fs/fs_Stdio.hpp>
#include <net/net_Service.hpp>
extern ui::QMenuApplication::Ref qapp;
extern ui::MenuApplication::Ref qapp;
extern cfg::TitleList list;
extern std::vector<cfg::TitleRecord> homebrew;
extern cfg::Config config;
@ -288,205 +288,215 @@ namespace ui
}
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)
{
pu::audio::Play(this->sfxTitleLaunch);
am::QMenuCommandWriter writer(am::QDaemonMessage::LaunchHomebrewLibApplet);
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;
bool hblaunch = true;
if(qapp->IsHomebrewSuspended())
{
if(qapp->EqualsSuspendedHomebrewPath(hb.nro_target.nro_path))
{
if(this->mode == 1) this->mode = 2;
hblaunch = false;
}
else
{
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
{
u32 realidx = index;
if(this->homebrew_mode) realidx--;
if(this->homebrew_mode)
auto &folder = cfg::FindFolderByName(list, this->curfolder);
s32 titleidx = realidx;
if(this->curfolder.empty())
{
auto hb = homebrew[realidx];
if(down & KEY_A)
if(realidx >= list.folders.size())
{
bool hblaunch = true;
if(qapp->IsHomebrewSuspended())
titleidx -= list.folders.size();
}
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;
hblaunch = false;
}
else
{
hblaunch = false;
this->HandleCloseSuspended();
hblaunch = !qapp->IsHomebrewSuspended();
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::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)
{
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)
{
if(!this->select_on) this->select_on = true;
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())
if((cfg::TitleType)title.title_type == cfg::TitleType::Homebrew)
{
titleidx -= list.folders.size();
}
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
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;
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())
{
@ -713,10 +723,10 @@ namespace ui
if(this->rawalpha == 255)
{
this->bgSuspendedRaw->SetAlphaFactor(this->rawalpha);
am::QMenuCommandWriter writer(am::QDaemonMessage::ResumeApplication);
am::MenuCommandWriter writer(am::DaemonMessage::ResumeApplication);
writer.FinishWrite();
am::QMenuCommandResultReader reader;
am::MenuCommandResultReader reader;
reader.FinishRead();
}
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);
if(sopt == 0)
{
am::QMenuCommandWriter writer(am::QDaemonMessage::TerminateApplication);
am::MenuCommandWriter writer(am::DaemonMessage::TerminateApplication);
writer.FinishWrite();
this->itemsMenu->UnsetSuspendedItem();
@ -828,7 +838,7 @@ namespace ui
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::LaunchHomebrewLibApplet);
am::MenuCommandWriter writer(am::DaemonMessage::LaunchHomebrewLibraryApplet);
writer.Write<hb::HbTargetParams>(ipt);
writer.FinishWrite();
@ -838,38 +848,46 @@ namespace ui
}
else if(launchmode == 2)
{
bool launch = true;
if(qapp->IsSuspended())
if(config.homebrew_title_application_id != 0)
{
launch = false;
this->HandleCloseSuspended();
if(!qapp->IsSuspended()) launch = true;
bool launch = true;
if(qapp->IsSuspended())
{
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);
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();
qapp->CreateShowDialog("Launch", "There is no title specified for homebrew to take over it.\nSelect one by pressing up over it.", { "Ok" }, true);
}
}
}
@ -878,11 +896,11 @@ namespace ui
{
auto uid = qapp->GetSelectedUser();
am::QMenuCommandWriter writer(am::QDaemonMessage::UserHasPassword);
am::MenuCommandWriter writer(am::DaemonMessage::UserHasPassword);
writer.Write<AccountUid>(uid);
writer.FinishWrite();
am::QMenuCommandResultReader res;
am::MenuCommandResultReader res;
res.FinishRead();
bool has_pass = R_SUCCEEDED(res.GetReadResult());
@ -929,12 +947,12 @@ namespace ui
rc = rc3;
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>(newpass);
writer.FinishWrite();
am::QMenuCommandResultReader reader;
am::MenuCommandResultReader reader;
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));
@ -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);
if(sopt2 == 0)
{
am::QMenuCommandWriter writer(am::QDaemonMessage::RemoveUserPassword);
am::MenuCommandWriter writer(am::DaemonMessage::RemoveUserPassword);
writer.Write<db::PassBlock>(oldpass);
writer.FinishWrite();
am::QMenuCommandResultReader reader;
am::MenuCommandResultReader reader;
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));
@ -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);
if(sopt == 0)
{
am::QMenuCommandWriter writer(am::QDaemonMessage::RegisterUserPassword);
am::MenuCommandWriter writer(am::DaemonMessage::RegisterUserPassword);
writer.Write<db::PassBlock>(newpass);
writer.FinishWrite();
am::QMenuCommandResultReader reader;
am::MenuCommandResultReader reader;
rc = reader.GetReadResult();
}
}
@ -998,9 +1016,9 @@ namespace ui
*(u32*)in = 7; // Type -> ShowMyProfile
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)
@ -1017,7 +1035,7 @@ namespace ui
{
if(logoff == 2)
{
am::QMenuCommandWriter writer(am::QDaemonMessage::TerminateApplication);
am::MenuCommandWriter writer(am::DaemonMessage::TerminateApplication);
writer.FinishWrite();
this->itemsMenu->UnsetSuspendedItem();
@ -1046,7 +1064,7 @@ namespace ui
webPageCreate(&web, url);
webConfigSetWhitelist(&web, ".*");
am::QMenuCommandWriter writer(am::QDaemonMessage::OpenWebPage);
am::MenuCommandWriter writer(am::DaemonMessage::OpenWebPage);
writer.Write<WebCommonConfig>(web);
writer.FinishWrite();
@ -1086,7 +1104,7 @@ namespace ui
arg2.take_over_connection = true;
arg2.left_justify = true;
am::LibraryAppletQMenuLaunchWith(AppletId_controller, 0,
am::LibraryAppletDaemonLaunchWith(AppletId_controller, 0,
[&](AppletHolder *h)
{
libappletPushInData(h, &arg1, sizeof(arg1));
@ -1097,7 +1115,7 @@ namespace ui
},
[&]() -> bool
{
return !am::QMenuIsHomePressed();
return !am::MenuIsHomePressed();
});
}
@ -1117,7 +1135,7 @@ namespace ui
void MenuLayout::HandleOpenAlbum()
{
am::QMenuCommandWriter writer(am::QDaemonMessage::OpenAlbum);
am::MenuCommandWriter writer(am::DaemonMessage::OpenAlbum);
writer.FinishWrite();
qapp->StopPlayBGM();

View file

@ -2,12 +2,12 @@
#include <os/os_Account.hpp>
#include <os/os_Misc.hpp>
#include <util/util_Convert.hpp>
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <fs/fs_Stdio.hpp>
#include <net/net_Service.hpp>
#include <am/am_LibraryApplet.hpp>
extern ui::QMenuApplication::Ref qapp;
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
@ -177,9 +177,9 @@ namespace ui
*(u32*)in = 1; // 0 = normal, 1 = qlaunch, 2 = starter?
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;
@ -270,7 +270,7 @@ namespace ui
{
qapp->CommonMenuOnLoop();
bool ret = am::QMenuIsHomePressed();
bool ret = am::MenuIsHomePressed();
if(down & KEY_B) ret = true;
if(ret)
{

View file

@ -1,10 +1,10 @@
#include <ui/ui_StartupLayout.hpp>
#include <os/os_Account.hpp>
#include <util/util_Convert.hpp>
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <fs/fs_Stdio.hpp>
extern ui::QMenuApplication::Ref qapp;
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
@ -66,11 +66,11 @@ namespace ui
rc = rc2;
if(R_SUCCEEDED(rc))
{
am::QMenuCommandWriter writer(am::QDaemonMessage::TryLogUser);
am::MenuCommandWriter writer(am::DaemonMessage::TryLogUser);
writer.Write<db::PassBlock>(pass);
writer.FinishWrite();
am::QMenuCommandResultReader reader;
am::MenuCommandResultReader reader;
rc = reader.GetReadResult();
reader.FinishRead();
@ -119,11 +119,11 @@ namespace ui
auto [rc, name] = os::GetAccountName(user);
if(R_FAILED(rc)) continue;
am::QMenuCommandWriter writer(am::QDaemonMessage::UserHasPassword);
am::MenuCommandWriter writer(am::DaemonMessage::UserHasPassword);
writer.Write<AccountUid>(user);
writer.FinishWrite();
am::QMenuCommandResultReader res;
am::MenuCommandResultReader res;
res.FinishRead();
bool has_pass = R_SUCCEEDED(res.GetReadResult());

View file

@ -1,10 +1,10 @@
#include <ui/ui_ThemeMenuLayout.hpp>
#include <os/os_Account.hpp>
#include <util/util_Convert.hpp>
#include <ui/ui_QMenuApplication.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <fs/fs_Stdio.hpp>
extern ui::QMenuApplication::Ref qapp;
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
@ -105,7 +105,7 @@ namespace ui
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(ret)
{