summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/kernel.cpp7
-rw-r--r--src/core/hle/kernel/process.cpp22
-rw-r--r--src/core/hle/kernel/process.h7
-rw-r--r--src/core/hle/kernel/svc.cpp20
-rw-r--r--src/core/hle/kernel/thread.h12
-rw-r--r--src/core/hle/kernel/wait_object.cpp2
-rw-r--r--src/core/hle/kernel/wait_object.h2
-rw-r--r--src/core/hle/service/am/am.cpp27
-rw-r--r--src/core/hle/service/am/applets/applets.cpp82
-rw-r--r--src/core/hle/service/am/applets/applets.h55
-rw-r--r--src/core/hle/service/am/applets/error.cpp182
-rw-r--r--src/core/hle/service/am/applets/error.h47
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp (renamed from src/core/hle/service/am/applets/stub_applet.cpp)56
-rw-r--r--src/core/hle/service/am/applets/general_backend.h48
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp6
-rw-r--r--src/core/hle/service/am/applets/profile_select.h4
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp7
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h4
-rw-r--r--src/core/hle/service/am/applets/stub_applet.h24
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp4
-rw-r--r--src/core/hle/service/am/applets/web_browser.h4
-rw-r--r--src/core/hle/service/audio/audctl.cpp30
-rw-r--r--src/core/hle/service/audio/audctl.h4
23 files changed, 556 insertions, 100 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index a38ee117b..757e5f21f 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -181,7 +181,12 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
void KernelCore::MakeCurrentProcess(Process* process) {
impl->current_process = process;
- Memory::SetCurrentPageTable(&process->VMManager().page_table);
+
+ if (process == nullptr) {
+ return;
+ }
+
+ Memory::SetCurrentPageTable(*process);
}
Process* KernelCore::CurrentProcess() {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0ace3d21c..20d01fc88 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -28,21 +28,20 @@ namespace {
*
* @param owner_process The parent process for the main thread
* @param kernel The kernel instance to create the main thread under.
- * @param entry_point The address at which the thread should start execution
* @param priority The priority to give the main thread
*/
-void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
- // Initialize new "main" thread
- const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
+void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
+ const auto& vm_manager = owner_process.VMManager();
+ const VAddr entry_point = vm_manager.GetCodeRegionBaseAddress();
+ const VAddr stack_top = vm_manager.GetTLSIORegionEndAddress();
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
owner_process.GetIdealCore(), stack_top, owner_process);
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
// Register 1 must be a handle to the main thread
- const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
- thread->SetGuestHandle(guest_handle);
- thread->GetContext().cpu_registers[1] = guest_handle;
+ const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
+ thread->GetContext().cpu_registers[1] = thread_handle;
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
thread->ResumeFromWait();
@@ -106,8 +105,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
is_64bit_process = metadata.Is64BitProgram();
vm_manager.Reset(metadata.GetAddressSpaceType());
- // Ensure that the potentially resized page table is seen by CPU backends.
- Memory::SetCurrentPageTable(&vm_manager.page_table);
const auto& caps = metadata.GetKernelCapabilities();
const auto capability_init_result =
@@ -119,7 +116,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
return handle_table.SetSize(capabilities.GetHandleTableSize());
}
-void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
+void Process::Run(s32 main_thread_priority, u64 stack_size) {
// The kernel always ensures that the given stack size is page aligned.
main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
@@ -135,7 +132,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
vm_manager.LogLayout();
ChangeStatus(ProcessStatus::Running);
- SetupMainThread(*this, kernel, entry_point, main_thread_priority);
+ SetupMainThread(*this, kernel, main_thread_priority);
}
void Process::PrepareForTermination() {
@@ -241,9 +238,6 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) {
MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData);
code_memory_size += module_.memory.size();
-
- // Clear instruction cache in CPU JIT
- system.InvalidateCpuInstructionCaches();
}
Process::Process(Core::System& system)
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index dda52f4c0..bf3b7eef3 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -225,9 +225,12 @@ public:
ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
/**
- * Applies address space changes and launches the process main thread.
+ * Starts the main application thread for this process.
+ *
+ * @param main_thread_priority The priority for the main thread.
+ * @param stack_size The stack size for the main thread in bytes.
*/
- void Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size);
+ void Run(s32 main_thread_priority, u64 stack_size);
/**
* Prepares a process for termination by stopping all of its threads
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index ea3fdc315..2dcf174c5 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1378,20 +1378,22 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
return ERR_INVALID_THREAD_PRIORITY;
}
- const std::string name = fmt::format("thread-{:X}", entry_point);
auto& kernel = system.Kernel();
CASCADE_RESULT(SharedPtr<Thread> thread,
- Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
+ Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top,
*current_process));
- const auto new_guest_handle = current_process->GetHandleTable().Create(thread);
- if (new_guest_handle.Failed()) {
+ const auto new_thread_handle = current_process->GetHandleTable().Create(thread);
+ if (new_thread_handle.Failed()) {
LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}",
- new_guest_handle.Code().raw);
- return new_guest_handle.Code();
+ new_thread_handle.Code().raw);
+ return new_thread_handle.Code();
}
- thread->SetGuestHandle(*new_guest_handle);
- *out_handle = *new_guest_handle;
+ *out_handle = *new_thread_handle;
+
+ // Set the thread name for debugging purposes.
+ thread->SetName(
+ fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
@@ -2286,7 +2288,7 @@ static const FunctionDef SVC_Table[] = {
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
{0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap<SignalToAddress>, "SignalToAddress"},
- {0x36, nullptr, "Unknown"},
+ {0x36, nullptr, "SynchronizePreemptionState"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 62ce7bfda..f07332f02 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -101,6 +101,11 @@ public:
std::string GetName() const override {
return name;
}
+
+ void SetName(std::string new_name) {
+ name = std::move(new_name);
+ }
+
std::string GetTypeName() const override {
return "Thread";
}
@@ -343,10 +348,6 @@ public:
arb_wait_address = address;
}
- void SetGuestHandle(Handle handle) {
- guest_handle = handle;
- }
-
bool HasWakeupCallback() const {
return wakeup_callback != nullptr;
}
@@ -440,9 +441,6 @@ private:
/// If waiting for an AddressArbiter, this is the address being waited on.
VAddr arb_wait_address{0};
- /// Handle used by guest emulated application to access this thread
- Handle guest_handle = 0;
-
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle = 0;
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 38d8a6e0c..0e96ba872 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -30,7 +30,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
waiting_threads.erase(itr);
}
-SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
+SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
Thread* candidate = nullptr;
u32 candidate_priority = THREADPRIO_LOWEST + 1;
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index 04464a51a..3271a30a7 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -54,7 +54,7 @@ public:
void WakeupWaitingThread(SharedPtr<Thread> thread);
/// Obtains the highest priority thread that is ready to run from this object's waiting list.
- SharedPtr<Thread> GetHighestPriorityReadyThread();
+ SharedPtr<Thread> GetHighestPriorityReadyThread() const;
/// Get a const reference to the waiting threads list for debug use
const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 1aa4ce1ac..26a665bfd 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -22,7 +22,6 @@
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/profile_select.h"
#include "core/hle/service/am/applets/software_keyboard.h"
-#include "core/hle/service/am/applets/stub_applet.h"
#include "core/hle/service/am/applets/web_browser.h"
#include "core/hle/service/am/idle.h"
#include "core/hle/service/am/omm.h"
@@ -42,12 +41,6 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
-enum class AppletId : u32 {
- ProfileSelect = 0x10,
- SoftwareKeyboard = 0x11,
- LibAppletOff = 0x17,
-};
-
constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
struct LaunchParameters {
@@ -886,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
-static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
- switch (id) {
- case AppletId::ProfileSelect:
- return std::make_shared<Applets::ProfileSelect>();
- case AppletId::SoftwareKeyboard:
- return std::make_shared<Applets::SoftwareKeyboard>();
- case AppletId::LibAppletOff:
- return std::make_shared<Applets::WebBrowser>();
- default:
- LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!",
- static_cast<u32>(id));
- return std::make_shared<Applets::StubApplet>();
- }
-}
-
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto applet_id = rp.PopRaw<AppletId>();
+ const auto applet_id = rp.PopRaw<Applets::AppletId>();
const auto applet_mode = rp.PopRaw<u32>();
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
static_cast<u32>(applet_id), applet_mode);
- const auto applet = GetAppletFromId(applet_id);
+ const auto& applet_manager{Core::System::GetInstance().GetAppletManager()};
+ const auto applet = applet_manager.GetApplet(applet_id);
if (applet == nullptr) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index a6064c63f..7f70b10df 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -5,11 +5,21 @@
#include <cstring>
#include "common/assert.h"
#include "core/core.h"
+#include "core/frontend/applets/error.h"
+#include "core/frontend/applets/general_frontend.h"
+#include "core/frontend/applets/profile_select.h"
+#include "core/frontend/applets/software_keyboard.h"
+#include "core/frontend/applets/web_browser.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/applets/error.h"
+#include "core/hle/service/am/applets/general_backend.h"
+#include "core/hle/service/am/applets/profile_select.h"
+#include "core/hle/service/am/applets/software_keyboard.h"
+#include "core/hle/service/am/applets/web_browser.h"
namespace Service::AM::Applets {
@@ -111,4 +121,76 @@ void Applet::Initialize() {
initialized = true;
}
+AppletManager::AppletManager() = default;
+
+AppletManager::~AppletManager() = default;
+
+void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
+ if (set.error != nullptr)
+ frontend.error = std::move(set.error);
+ if (set.photo_viewer != nullptr)
+ frontend.photo_viewer = std::move(set.photo_viewer);
+ if (set.profile_select != nullptr)
+ frontend.profile_select = std::move(set.profile_select);
+ if (set.software_keyboard != nullptr)
+ frontend.software_keyboard = std::move(set.software_keyboard);
+ if (set.web_browser != nullptr)
+ frontend.web_browser = std::move(set.web_browser);
+}
+
+void AppletManager::SetDefaultAppletFrontendSet() {
+ frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
+ frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
+ frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
+ frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
+ frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
+}
+
+void AppletManager::SetDefaultAppletsIfMissing() {
+ if (frontend.error == nullptr) {
+ frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
+ }
+
+ if (frontend.photo_viewer == nullptr) {
+ frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
+ }
+
+ if (frontend.profile_select == nullptr) {
+ frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
+ }
+
+ if (frontend.software_keyboard == nullptr) {
+ frontend.software_keyboard =
+ std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
+ }
+
+ if (frontend.web_browser == nullptr) {
+ frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
+ }
+}
+
+void AppletManager::ClearAll() {
+ frontend = {};
+}
+
+std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
+ switch (id) {
+ case AppletId::Error:
+ return std::make_shared<Error>(*frontend.error);
+ case AppletId::ProfileSelect:
+ return std::make_shared<ProfileSelect>(*frontend.profile_select);
+ case AppletId::SoftwareKeyboard:
+ return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard);
+ case AppletId::PhotoViewer:
+ return std::make_shared<PhotoViewer>(*frontend.photo_viewer);
+ case AppletId::LibAppletOff:
+ return std::make_shared<WebBrowser>(*frontend.web_browser);
+ default:
+ UNIMPLEMENTED_MSG(
+ "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
+ static_cast<u8>(id));
+ return std::make_shared<StubApplet>();
+ }
+}
+
} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 37424c379..7f932672c 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -12,12 +12,43 @@
union ResultCode;
+namespace Core::Frontend {
+class ErrorApplet;
+class PhotoViewerApplet;
+class ProfileSelectApplet;
+class SoftwareKeyboardApplet;
+class WebBrowserApplet;
+} // namespace Core::Frontend
+
namespace Service::AM {
class IStorage;
namespace Applets {
+enum class AppletId : u32 {
+ OverlayDisplay = 0x02,
+ QLaunch = 0x03,
+ Starter = 0x04,
+ Auth = 0x0A,
+ Cabinet = 0x0B,
+ Controller = 0x0C,
+ DataErase = 0x0D,
+ Error = 0x0E,
+ NetConnect = 0x0F,
+ ProfileSelect = 0x10,
+ SoftwareKeyboard = 0x11,
+ MiiEdit = 0x12,
+ LibAppletWeb = 0x13,
+ LibAppletShop = 0x14,
+ PhotoViewer = 0x15,
+ Settings = 0x16,
+ LibAppletOff = 0x17,
+ LibAppletWhitelisted = 0x18,
+ LibAppletAuth = 0x19,
+ MyPage = 0x1A,
+};
+
class AppletDataBroker final {
public:
AppletDataBroker();
@@ -105,5 +136,29 @@ protected:
bool initialized = false;
};
+struct AppletFrontendSet {
+ std::unique_ptr<Core::Frontend::ErrorApplet> error;
+ std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer;
+ std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select;
+ std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
+ std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
+};
+
+class AppletManager {
+public:
+ AppletManager();
+ ~AppletManager();
+
+ void SetAppletFrontendSet(AppletFrontendSet set);
+ void SetDefaultAppletFrontendSet();
+ void SetDefaultAppletsIfMissing();
+ void ClearAll();
+
+ std::shared_ptr<Applet> GetApplet(AppletId id) const;
+
+private:
+ AppletFrontendSet frontend;
+};
+
} // namespace Applets
} // namespace Service::AM
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
new file mode 100644
index 000000000..04774bedc
--- /dev/null
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -0,0 +1,182 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+#include <cstring>
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "common/string_util.h"
+#include "core/core.h"
+#include "core/frontend/applets/error.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applets/error.h"
+
+namespace Service::AM::Applets {
+
+#pragma pack(push, 4)
+struct ShowError {
+ u8 mode;
+ bool jump;
+ INSERT_PADDING_BYTES(4);
+ bool use_64bit_error_code;
+ INSERT_PADDING_BYTES(1);
+ u64 error_code_64;
+ u32 error_code_32;
+};
+static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
+#pragma pack(pop)
+
+struct ShowErrorRecord {
+ u8 mode;
+ bool jump;
+ INSERT_PADDING_BYTES(6);
+ u64 error_code_64;
+ u64 posix_time;
+};
+static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect size.");
+
+struct SystemErrorArg {
+ u8 mode;
+ bool jump;
+ INSERT_PADDING_BYTES(6);
+ u64 error_code_64;
+ std::array<char, 8> language_code;
+ std::array<char, 0x800> main_text;
+ std::array<char, 0x800> detail_text;
+};
+static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size.");
+
+struct ApplicationErrorArg {
+ u8 mode;
+ bool jump;
+ INSERT_PADDING_BYTES(6);
+ u32 error_code;
+ std::array<char, 8> language_code;
+ std::array<char, 0x800> main_text;
+ std::array<char, 0x800> detail_text;
+};
+static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size.");
+
+union Error::ErrorArguments {
+ ShowError error;
+ ShowErrorRecord error_record;
+ SystemErrorArg system_error;
+ ApplicationErrorArg application_error;
+};
+
+namespace {
+template <typename T>
+void CopyArgumentData(const std::vector<u8>& data, T& variable) {
+ ASSERT(data.size() >= sizeof(T));
+ std::memcpy(&variable, data.data(), sizeof(T));
+}
+
+ResultCode Decode64BitError(u64 error) {
+ const auto description = (error >> 32) & 0x1FFF;
+ auto module = error & 0x3FF;
+ if (module >= 2000)
+ module -= 2000;
+ module &= 0x1FF;
+ return {static_cast<ErrorModule>(module), static_cast<u32>(description)};
+}
+
+} // Anonymous namespace
+
+Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {}
+
+Error::~Error() = default;
+
+void Error::Initialize() {
+ Applet::Initialize();
+ args = std::make_unique<ErrorArguments>();
+ complete = false;
+
+ const auto storage = broker.PopNormalDataToApplet();
+ ASSERT(storage != nullptr);
+ const auto data = storage->GetData();
+
+ ASSERT(!data.empty());
+ std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode));
+
+ switch (mode) {
+ case ErrorAppletMode::ShowError:
+ CopyArgumentData(data, args->error);
+ if (args->error.use_64bit_error_code) {
+ error_code = Decode64BitError(args->error.error_code_64);
+ } else {
+ error_code = ResultCode(args->error.error_code_32);
+ }
+ break;
+ case ErrorAppletMode::ShowSystemError:
+ CopyArgumentData(data, args->system_error);
+ error_code = ResultCode(Decode64BitError(args->system_error.error_code_64));
+ break;
+ case ErrorAppletMode::ShowApplicationError:
+ CopyArgumentData(data, args->application_error);
+ error_code = ResultCode(args->application_error.error_code);
+ break;
+ case ErrorAppletMode::ShowErrorRecord:
+ CopyArgumentData(data, args->error_record);
+ error_code = Decode64BitError(args->error_record.error_code_64);
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
+ }
+}
+
+bool Error::TransactionComplete() const {
+ return complete;
+}
+
+ResultCode Error::GetStatus() const {
+ return RESULT_SUCCESS;
+}
+
+void Error::ExecuteInteractive() {
+ UNREACHABLE_MSG("Unexpected interactive applet data!");
+}
+
+void Error::Execute() {
+ if (complete) {
+ return;
+ }
+
+ const auto callback = [this] { DisplayCompleted(); };
+
+ switch (mode) {
+ case ErrorAppletMode::ShowError:
+ frontend.ShowError(error_code, callback);
+ break;
+ case ErrorAppletMode::ShowSystemError:
+ case ErrorAppletMode::ShowApplicationError: {
+ const auto system = mode == ErrorAppletMode::ShowSystemError;
+ const auto& main_text =
+ system ? args->system_error.main_text : args->application_error.main_text;
+ const auto& detail_text =
+ system ? args->system_error.detail_text : args->application_error.detail_text;
+
+ frontend.ShowCustomErrorText(
+ error_code,
+ Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()),
+ Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()),
+ callback);
+ break;
+ }
+ case ErrorAppletMode::ShowErrorRecord:
+ frontend.ShowErrorWithTimestamp(
+ error_code, std::chrono::seconds{args->error_record.posix_time}, callback);
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
+ DisplayCompleted();
+ }
+}
+
+void Error::DisplayCompleted() {
+ complete = true;
+ broker.PushNormalDataFromApplet(IStorage{{}});
+ broker.SignalStateChanged();
+}
+
+} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h
new file mode 100644
index 000000000..a3590d181
--- /dev/null
+++ b/src/core/hle/service/am/applets/error.h
@@ -0,0 +1,47 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/result.h"
+#include "core/hle/service/am/applets/applets.h"
+
+namespace Service::AM::Applets {
+
+enum class ErrorAppletMode : u8 {
+ ShowError = 0,
+ ShowSystemError = 1,
+ ShowApplicationError = 2,
+ ShowEula = 3,
+ ShowErrorPctl = 4,
+ ShowErrorRecord = 5,
+ ShowUpdateEula = 8,
+};
+
+class Error final : public Applet {
+public:
+ explicit Error(const Core::Frontend::ErrorApplet& frontend);
+ ~Error() override;
+
+ void Initialize() override;
+
+ bool TransactionComplete() const override;
+ ResultCode GetStatus() const override;
+ void ExecuteInteractive() override;
+ void Execute() override;
+
+ void DisplayCompleted();
+
+private:
+ union ErrorArguments;
+
+ const Core::Frontend::ErrorApplet& frontend;
+ ResultCode error_code = RESULT_SUCCESS;
+ ErrorAppletMode mode = ErrorAppletMode::ShowError;
+ std::unique_ptr<ErrorArguments> args;
+
+ bool complete = false;
+};
+
+} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/stub_applet.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index ed166b87d..c591b9ac2 100644
--- a/src/core/hle/service/am/applets/stub_applet.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -4,11 +4,15 @@
#include <string>
+#include "common/assert.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "core/core.h"
+#include "core/frontend/applets/general_frontend.h"
+#include "core/hle/kernel/process.h"
#include "core/hle/result.h"
#include "core/hle/service/am/am.h"
-#include "core/hle/service/am/applets/stub_applet.h"
+#include "core/hle/service/am/applets/general_backend.h"
namespace Service::AM::Applets {
@@ -30,6 +34,55 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) {
}
}
+PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {}
+
+PhotoViewer::~PhotoViewer() = default;
+
+void PhotoViewer::Initialize() {
+ Applet::Initialize();
+ complete = false;
+
+ const auto storage = broker.PopNormalDataToApplet();
+ ASSERT(storage != nullptr);
+ const auto data = storage->GetData();
+ ASSERT(!data.empty());
+ mode = static_cast<PhotoViewerAppletMode>(data[0]);
+}
+
+bool PhotoViewer::TransactionComplete() const {
+ return complete;
+}
+
+ResultCode PhotoViewer::GetStatus() const {
+ return RESULT_SUCCESS;
+}
+
+void PhotoViewer::ExecuteInteractive() {
+ UNREACHABLE_MSG("Unexpected interactive applet data.");
+}
+
+void PhotoViewer::Execute() {
+ if (complete)
+ return;
+
+ const auto callback = [this] { ViewFinished(); };
+ switch (mode) {
+ case PhotoViewerAppletMode::CurrentApp:
+ frontend.ShowPhotosForApplication(Core::CurrentProcess()->GetTitleID(), callback);
+ break;
+ case PhotoViewerAppletMode::AllApps:
+ frontend.ShowAllPhotos(callback);
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast<u8>(mode));
+ }
+}
+
+void PhotoViewer::ViewFinished() {
+ broker.PushNormalDataFromApplet(IStorage{{}});
+ broker.SignalStateChanged();
+}
+
StubApplet::StubApplet() = default;
StubApplet::~StubApplet() = default;
@@ -67,4 +120,5 @@ void StubApplet::Execute() {
broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
broker.SignalStateChanged();
}
+
} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h
new file mode 100644
index 000000000..2dd255d7c
--- /dev/null
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -0,0 +1,48 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/am/applets/applets.h"
+
+namespace Service::AM::Applets {
+
+enum class PhotoViewerAppletMode : u8 {
+ CurrentApp = 0,
+ AllApps = 1,
+};
+
+class PhotoViewer final : public Applet {
+public:
+ explicit PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend);
+ ~PhotoViewer() override;
+
+ void Initialize() override;
+ bool TransactionComplete() const override;
+ ResultCode GetStatus() const override;
+ void ExecuteInteractive() override;
+ void Execute() override;
+
+ void ViewFinished();
+
+private:
+ const Core::Frontend::PhotoViewerApplet& frontend;
+ bool complete = false;
+ PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
+};
+
+class StubApplet final : public Applet {
+public:
+ StubApplet();
+ ~StubApplet() override;
+
+ void Initialize() override;
+
+ bool TransactionComplete() const override;
+ ResultCode GetStatus() const override;
+ void ExecuteInteractive() override;
+ void Execute() override;
+};
+
+} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 14e2a1fee..d113bd2eb 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -15,7 +15,9 @@ namespace Service::AM::Applets {
constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
-ProfileSelect::ProfileSelect() = default;
+ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend)
+ : frontend(frontend) {}
+
ProfileSelect::~ProfileSelect() = default;
void ProfileSelect::Initialize() {
@@ -51,8 +53,6 @@ void ProfileSelect::Execute() {
return;
}
- const auto& frontend{Core::System::GetInstance().GetProfileSelector()};
-
frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
}
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
index 787485f22..a2ac6cf50 100644
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
class ProfileSelect final : public Applet {
public:
- ProfileSelect();
+ explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend);
~ProfileSelect() override;
void Initialize() override;
@@ -41,6 +41,8 @@ public:
void SelectionComplete(std::optional<Account::UUID> uuid);
private:
+ const Core::Frontend::ProfileSelectApplet& frontend;
+
UserSelectionConfig config;
bool complete = false;
ResultCode status = RESULT_SUCCESS;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 8c5bd6059..e197990f7 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -39,7 +39,8 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
return params;
}
-SoftwareKeyboard::SoftwareKeyboard() = default;
+SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend)
+ : frontend(frontend) {}
SoftwareKeyboard::~SoftwareKeyboard() = default;
@@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() {
if (status == INTERACTIVE_STATUS_OK) {
complete = true;
} else {
- const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
-
std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
frontend.SendTextCheckDialog(
@@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() {
return;
}
- const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
-
const auto parameters = ConvertToFrontendParameters(config, initial_text);
frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); },
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index b93a30d28..0fbc43e51 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
class SoftwareKeyboard final : public Applet {
public:
- SoftwareKeyboard();
+ explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend);
~SoftwareKeyboard() override;
void Initialize() override;
@@ -68,6 +68,8 @@ public:
void WriteText(std::optional<std::u16string> text);
private:
+ const Core::Frontend::SoftwareKeyboardApplet& frontend;
+
KeyboardConfig config;
std::u16string initial_text;
bool complete = false;
diff --git a/src/core/hle/service/am/applets/stub_applet.h b/src/core/hle/service/am/applets/stub_applet.h
deleted file mode 100644
index 7d8dc968d..000000000
--- a/src/core/hle/service/am/applets/stub_applet.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "core/hle/service/am/applets/applets.h"
-
-namespace Service::AM::Applets {
-
-class StubApplet final : public Applet {
-public:
- StubApplet();
- ~StubApplet() override;
-
- void Initialize() override;
-
- bool TransactionComplete() const override;
- ResultCode GetStatus() const override;
- void ExecuteInteractive() override;
- void Execute() override;
-};
-
-} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 7e17df98a..7878f5136 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -95,7 +95,7 @@ static FileSys::VirtualFile GetManualRomFS() {
return nullptr;
}
-WebBrowser::WebBrowser() = default;
+WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {}
WebBrowser::~WebBrowser() = default;
@@ -152,8 +152,6 @@ void WebBrowser::Execute() {
return;
}
- auto& frontend{Core::System::GetInstance().GetWebBrowser()};
-
frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
}
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index b9e228fac..7e0f34c7d 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -12,7 +12,7 @@ namespace Service::AM::Applets {
class WebBrowser final : public Applet {
public:
- WebBrowser();
+ WebBrowser(Core::Frontend::WebBrowserApplet& frontend);
~WebBrowser() override;
void Initialize() override;
@@ -32,6 +32,8 @@ public:
void Finalize();
private:
+ Core::Frontend::WebBrowserApplet& frontend;
+
bool complete = false;
bool unpacked = false;
ResultCode status = RESULT_SUCCESS;
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
index b6b71f966..f43e512e9 100644
--- a/src/core/hle/service/audio/audctl.cpp
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
#include "core/hle/service/audio/audctl.h"
namespace Service::Audio {
@@ -11,8 +13,8 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
static const FunctionInfo functions[] = {
{0, nullptr, "GetTargetVolume"},
{1, nullptr, "SetTargetVolume"},
- {2, nullptr, "GetTargetVolumeMin"},
- {3, nullptr, "GetTargetVolumeMax"},
+ {2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"},
+ {3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"},
{4, nullptr, "IsTargetMute"},
{5, nullptr, "SetTargetMute"},
{6, nullptr, "IsTargetConnected"},
@@ -44,4 +46,28 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
AudCtl::~AudCtl() = default;
+void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Audio, "called.");
+
+ // This service function is currently hardcoded on the
+ // actual console to this value (as of 6.0.0).
+ constexpr s32 target_min_volume = 0;
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(target_min_volume);
+}
+
+void AudCtl::GetTargetVolumeMax(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Audio, "called.");
+
+ // This service function is currently hardcoded on the
+ // actual console to this value (as of 6.0.0).
+ constexpr s32 target_max_volume = 15;
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(target_max_volume);
+}
+
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
index 9d2d9e83b..c7fafc02e 100644
--- a/src/core/hle/service/audio/audctl.h
+++ b/src/core/hle/service/audio/audctl.h
@@ -12,6 +12,10 @@ class AudCtl final : public ServiceFramework<AudCtl> {
public:
explicit AudCtl();
~AudCtl() override;
+
+private:
+ void GetTargetVolumeMin(Kernel::HLERequestContext& ctx);
+ void GetTargetVolumeMax(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Audio