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

View file

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

View file

@ -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/", &params, 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/", &params, sizeof(params)); UL_R_TRY(ecs::RegisterLaunchAsApplet(config.homebrew_applet_program_id, 0, "/ulaunch/bin/uHbTarget/applet/", &params, 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;
} }

View file

@ -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)
{ {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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()); \

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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 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());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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)
{ {

View file

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

View file

@ -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)
{ {