mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-23 00:59:17 +01:00
Write ApplicationErrorArg
ErrorApplet
s to log
These applets are used by applications to display a custom error message to the user. Both the error message and the detailed error message are printed to the error log. Co-authored-by: lynxnb <niccolo.betto@gmail.com>
This commit is contained in:
parent
f9a0394577
commit
942e22f275
@ -262,6 +262,7 @@ add_library(skyline SHARED
|
||||
${source_DIR}/skyline/services/btm/IBtmUserCore.cpp
|
||||
${source_DIR}/skyline/applet/applet_creator.cpp
|
||||
${source_DIR}/skyline/applet/controller_applet.cpp
|
||||
${source_DIR}/skyline/applet/error_applet.cpp
|
||||
${source_DIR}/skyline/applet/player_select_applet.cpp
|
||||
${source_DIR}/skyline/applet/swkbd/software_keyboard_applet.cpp
|
||||
${source_DIR}/skyline/applet/swkbd/software_keyboard_config.cpp
|
||||
|
@ -1,9 +1,10 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "controller_applet.h"
|
||||
#include "player_select_applet.h"
|
||||
#include "applet_creator.h"
|
||||
#include "controller_applet.h"
|
||||
#include "error_applet.h"
|
||||
#include "player_select_applet.h"
|
||||
#include "swkbd/software_keyboard_applet.h"
|
||||
|
||||
namespace skyline::applet {
|
||||
@ -20,8 +21,10 @@ namespace skyline::applet {
|
||||
return std::make_shared<PlayerSelectApplet>(state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode);
|
||||
case AppletId::LibraryAppletSwkbd:
|
||||
return std::make_shared<swkbd::SoftwareKeyboardApplet>(state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode);
|
||||
case AppletId::LibraryAppletError:
|
||||
return std::make_shared<ErrorApplet>(state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode);
|
||||
default:
|
||||
throw exception("Unimplemented Applet: 0x{:X} ({})", static_cast<u32>(appletId), ToString(appletId));
|
||||
throw exception{"Unimplemented Applet: 0x{:X} ({})", static_cast<u32>(appletId), ToString(appletId)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace skyline::applet {
|
||||
std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet,
|
||||
std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet,
|
||||
service::applet::LibraryAppletMode appletMode)
|
||||
: IApplet(state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode) {}
|
||||
: IApplet{state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode} {}
|
||||
|
||||
void ControllerApplet::HandleShowControllerSupport(input::NpadStyleSet styleSet, ControllerAppletVersion version, span<u8> arg) {
|
||||
// Generic macro due to both versions of arguments sharing the same fields but having different layouts
|
||||
@ -82,7 +82,7 @@ namespace skyline::applet {
|
||||
}
|
||||
}
|
||||
|
||||
std::scoped_lock lock{inputDataMutex};
|
||||
std::scoped_lock lock{normalInputDataMutex};
|
||||
switch (argPrivate.mode) {
|
||||
case ControllerSupportMode::ShowControllerSupport:
|
||||
HandleShowControllerSupport(argPrivate.styleSet, appletVersion, normalInputData.front()->GetSpan());
|
||||
@ -100,15 +100,14 @@ namespace skyline::applet {
|
||||
// Notify the guest that we've finished running
|
||||
onAppletStateChanged->Signal();
|
||||
return {};
|
||||
};
|
||||
}
|
||||
|
||||
Result ControllerApplet::GetResult() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void ControllerApplet::PushNormalDataToApplet(std::shared_ptr<service::am::IStorage> data) {
|
||||
std::scoped_lock lock{inputDataMutex};
|
||||
normalInputData.emplace(std::move(data));
|
||||
PushNormalInput(data);
|
||||
}
|
||||
|
||||
void ControllerApplet::PushInteractiveDataToApplet(std::shared_ptr<service::am::IStorage> data) {}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <services/am/applet/IApplet.h>
|
||||
#include <services/applet/common_arguments.h>
|
||||
#include <input/npad_device.h>
|
||||
@ -10,7 +11,7 @@ namespace skyline::applet {
|
||||
/**
|
||||
* @brief The Controller applet is responsible for notifiying the user of a games controller requirements and for allowing user management og controllers
|
||||
*/
|
||||
class ControllerApplet : public service::am::IApplet {
|
||||
class ControllerApplet : public service::am::IApplet, service::am::EnableNormalQueue {
|
||||
private:
|
||||
/**
|
||||
* @brief The version of the controller applet interface that an application supports
|
||||
@ -98,17 +99,6 @@ namespace skyline::applet {
|
||||
};
|
||||
static_assert(sizeof(ControllerSupportResultInfo) == 0xC);
|
||||
|
||||
std::mutex inputDataMutex;
|
||||
std::queue<std::shared_ptr<service::am::IStorage>> normalInputData;
|
||||
|
||||
template<typename T>
|
||||
T PopNormalInput() {
|
||||
std::scoped_lock lock{inputDataMutex};
|
||||
auto data{normalInputData.front()->GetSpan().as<T>()};
|
||||
normalInputData.pop();
|
||||
return static_cast<T>(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the 'ShowControllerSupport' mode of the controller applet
|
||||
*/
|
||||
|
55
app/src/main/cpp/skyline/applet/error_applet.cpp
Normal file
55
app/src/main/cpp/skyline/applet/error_applet.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "error_applet.h"
|
||||
#include "services/am/storage/ObjIStorage.h"
|
||||
|
||||
namespace skyline::applet {
|
||||
ErrorApplet::ErrorApplet(const DeviceState &state,
|
||||
service::ServiceManager &manager,
|
||||
std::shared_ptr<kernel::type::KEvent> onAppletStateChanged,
|
||||
std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet,
|
||||
std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet,
|
||||
service::applet::LibraryAppletMode appletMode)
|
||||
: IApplet{state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode} {}
|
||||
|
||||
Result ErrorApplet::Start() {
|
||||
auto commonArg{PopNormalInput<service::applet::CommonArguments>()};
|
||||
|
||||
errorStorage = PopNormalInput();
|
||||
auto errorCommonHeader{errorStorage->GetSpan().as<ErrorCommonHeader>()};
|
||||
Logger::Debug("ErrorApplet: version: 0x{:X}, type: 0x{:X}", commonArg.apiVersion, errorCommonHeader.type);
|
||||
|
||||
switch (errorCommonHeader.type) {
|
||||
case ErrorType::ApplicationErrorArg:
|
||||
HandleApplicationErrorArg();
|
||||
break;
|
||||
default:
|
||||
throw exception("ErrorApplet type 0x{:X} is not implemented", errorCommonHeader.type);
|
||||
}
|
||||
|
||||
// Notify the guest that we've finished running
|
||||
onAppletStateChanged->Signal();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void ErrorApplet::HandleApplicationErrorArg() {
|
||||
auto applicationErrorStorage{errorStorage->GetSpan().as<ApplicationErrorArg>()};
|
||||
|
||||
if (applicationErrorStorage.fullscreenMessage[0] == '\0')
|
||||
Logger::ErrorNoPrefix("Application Error: {}", applicationErrorStorage.dialogMessage.data());
|
||||
else
|
||||
Logger::ErrorNoPrefix("Application Error: {}\nFull message: {}", applicationErrorStorage.dialogMessage.data(), applicationErrorStorage.fullscreenMessage.data());
|
||||
}
|
||||
|
||||
Result ErrorApplet::GetResult() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void ErrorApplet::PushNormalDataToApplet(std::shared_ptr<service::am::IStorage> data) {
|
||||
PushNormalInput(data);
|
||||
}
|
||||
|
||||
void ErrorApplet::PushInteractiveDataToApplet(std::shared_ptr<service::am::IStorage> data) {}
|
||||
}
|
70
app/src/main/cpp/skyline/applet/error_applet.h
Normal file
70
app/src/main/cpp/skyline/applet/error_applet.h
Normal file
@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
// Copyright © 2020 Ryujinx Team and Contributors (https://github.com/ryujinx/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <services/am/applet/IApplet.h>
|
||||
#include "common/language.h"
|
||||
|
||||
namespace skyline::applet {
|
||||
/**
|
||||
* @brief The Error Applet is utilized by the guest to display an error to the user, this class prints the supplied error to the logger
|
||||
* @url https://switchbrew.org/wiki/Error_Applet
|
||||
* @url https://switchbrew.org/wiki/Error_applet
|
||||
*/
|
||||
class ErrorApplet : public service::am::IApplet, service::am::EnableNormalQueue {
|
||||
private:
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
enum class ErrorType : u8 {
|
||||
ErrorCommonArg = 0,
|
||||
SystemErrorArg = 1,
|
||||
ApplicationErrorArg = 2,
|
||||
ErrorEulaArg = 3,
|
||||
ErrorPctlArg = 4,
|
||||
ErrorRecordArg = 5,
|
||||
SystemUpdateEulaArg = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Error_Applet#ErrorCommonHeader
|
||||
*/
|
||||
struct ErrorCommonHeader {
|
||||
ErrorType type;
|
||||
u8 jump;
|
||||
u8 _pad_[0x3];
|
||||
u8 contextFlag;
|
||||
u8 resultFlag;
|
||||
u8 contextFlag2;
|
||||
};
|
||||
static_assert(sizeof(ErrorCommonHeader) == 0x8);
|
||||
|
||||
struct ApplicationErrorArg {
|
||||
ErrorCommonHeader commonHeader;
|
||||
u32 errorNumber;
|
||||
LanguageCode languageCode;
|
||||
std::array<char, 0x800> dialogMessage;
|
||||
std::array<char, 0x800> fullscreenMessage; //!< The message displayed when the user clicks on "Details", when not set this disables displaying Details
|
||||
};
|
||||
static_assert(sizeof(ApplicationErrorArg) == 0x1014);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
std::shared_ptr<service::am::IStorage> errorStorage;
|
||||
|
||||
void HandleApplicationErrorArg();
|
||||
|
||||
public:
|
||||
ErrorApplet(const DeviceState &state, service::ServiceManager &manager, std::shared_ptr<kernel::type::KEvent> onAppletStateChanged, std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet, std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet, service::applet::LibraryAppletMode appletMode);
|
||||
|
||||
Result Start() override;
|
||||
|
||||
Result GetResult() override;
|
||||
|
||||
void PushNormalDataToApplet(std::shared_ptr<service::am::IStorage> data) override;
|
||||
|
||||
void PushInteractiveDataToApplet(std::shared_ptr<service::am::IStorage> data) override;
|
||||
};
|
||||
}
|
@ -11,7 +11,7 @@ namespace skyline::applet {
|
||||
std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet,
|
||||
std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet,
|
||||
service::applet::LibraryAppletMode appletMode)
|
||||
: IApplet(state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode) {}
|
||||
: IApplet{state, manager, std::move(onAppletStateChanged), std::move(onNormalDataPushFromApplet), std::move(onInteractiveDataPushFromApplet), appletMode} {}
|
||||
|
||||
Result PlayerSelectApplet::Start() {
|
||||
// Return default user
|
||||
|
@ -74,7 +74,7 @@ namespace skyline::applet::swkbd {
|
||||
}
|
||||
|
||||
Result SoftwareKeyboardApplet::Start() {
|
||||
std::scoped_lock lock{inputDataMutex};
|
||||
std::scoped_lock lock{normalInputDataMutex};
|
||||
auto commonArgs{normalInputData.front()->GetSpan().as<service::applet::CommonArguments>()};
|
||||
normalInputData.pop();
|
||||
|
||||
@ -135,8 +135,7 @@ namespace skyline::applet::swkbd {
|
||||
}
|
||||
|
||||
void SoftwareKeyboardApplet::PushNormalDataToApplet(std::shared_ptr<service::am::IStorage> data) {
|
||||
std::scoped_lock lock{inputDataMutex};
|
||||
normalInputData.emplace(data);
|
||||
PushNormalInput(data);
|
||||
}
|
||||
|
||||
void SoftwareKeyboardApplet::PushInteractiveDataToApplet(std::shared_ptr<service::am::IStorage> data) {
|
||||
|
@ -15,7 +15,7 @@ namespace skyline::applet::swkbd {
|
||||
* @url https://switchbrew.org/wiki/Software_Keyboard
|
||||
* @brief An implementation for the Software Keyboard (swkbd) Applet which handles translating guest applet transactions to the appropriate host behavior
|
||||
*/
|
||||
class SoftwareKeyboardApplet : public service::am::IApplet {
|
||||
class SoftwareKeyboardApplet : public service::am::IApplet, service::am::EnableNormalQueue {
|
||||
private:
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Software_Keyboard#CloseResult
|
||||
@ -73,8 +73,6 @@ namespace skyline::applet::swkbd {
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
std::mutex inputDataMutex;
|
||||
std::queue<std::shared_ptr<service::am::IStorage>> normalInputData;
|
||||
KeyboardConfigVB config{};
|
||||
bool validationPending{};
|
||||
std::u16string currentText{};
|
||||
|
@ -7,7 +7,7 @@
|
||||
namespace skyline::applet::swkbd {
|
||||
KeyboardConfigVB::KeyboardConfigVB() = default;
|
||||
|
||||
KeyboardConfigVB::KeyboardConfigVB(const KeyboardConfigV7 &v7config) : commonConfig(v7config.commonConfig), separateTextPos(v7config.separateTextPos) {}
|
||||
KeyboardConfigVB::KeyboardConfigVB(const KeyboardConfigV7 &v7config) : commonConfig{v7config.commonConfig}, separateTextPos{v7config.separateTextPos} {}
|
||||
|
||||
KeyboardConfigVB::KeyboardConfigVB(const KeyboardConfigV0 &v0config) : commonConfig(v0config.commonConfig) {}
|
||||
KeyboardConfigVB::KeyboardConfigVB(const KeyboardConfigV0 &v0config) : commonConfig{v0config.commonConfig} {}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <kernel/types/KEvent.h>
|
||||
#include <services/applet/common_arguments.h>
|
||||
|
||||
|
||||
namespace skyline::service::am {
|
||||
/**
|
||||
* @brief The base class all Applets have to inherit from
|
||||
@ -70,4 +69,60 @@ namespace skyline::service::am {
|
||||
*/
|
||||
std::shared_ptr<IStorage> PopInteractiveAndClear();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Utility class for applets that need to queue the normal data sent to them
|
||||
*/
|
||||
class EnableNormalQueue {
|
||||
protected:
|
||||
std::mutex normalInputDataMutex;
|
||||
std::queue<std::shared_ptr<service::am::IStorage>> normalInputData;
|
||||
|
||||
std::shared_ptr<service::am::IStorage> PopNormalInput() {
|
||||
std::scoped_lock lock{normalInputDataMutex};
|
||||
auto data{normalInputData.front()};
|
||||
normalInputData.pop();
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T PopNormalInput() {
|
||||
std::scoped_lock lock{normalInputDataMutex};
|
||||
auto data{normalInputData.front()->GetSpan().as<T>()};
|
||||
normalInputData.pop();
|
||||
return data;
|
||||
}
|
||||
|
||||
void PushNormalInput(std::shared_ptr<service::am::IStorage> data) {
|
||||
normalInputData.emplace(data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Utility class for applets that need to queue the interactive data sent to them
|
||||
*/
|
||||
class EnableInteractiveQueue {
|
||||
protected:
|
||||
std::mutex interactiveInputDataMutex;
|
||||
std::queue<std::shared_ptr<service::am::IStorage>> interactiveInputData;
|
||||
|
||||
std::shared_ptr<service::am::IStorage> PopInteractiveInput() {
|
||||
std::scoped_lock lock{interactiveInputDataMutex};
|
||||
auto data{interactiveInputData.front()};
|
||||
interactiveInputData.pop();
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T PopInteractiveInput() {
|
||||
std::scoped_lock lock{interactiveInputDataMutex};
|
||||
auto data{interactiveInputData.front()->GetSpan().as<T>()};
|
||||
interactiveInputData.pop();
|
||||
return data;
|
||||
}
|
||||
|
||||
void PushInteractiveInput(std::shared_ptr<service::am::IStorage> data) {
|
||||
interactiveInputData.emplace(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user