2018-01-13 16:22:39 -05:00
|
|
|
// Copyright 2018 yuzu emulator team
|
2017-10-14 22:50:04 -04:00
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2019-03-17 20:47:03 -04:00
|
|
|
#include <algorithm>
|
2018-08-21 10:59:37 -04:00
|
|
|
#include <array>
|
2018-03-04 13:03:58 -05:00
|
|
|
#include <cinttypes>
|
2018-10-10 21:49:20 -04:00
|
|
|
#include <cstring>
|
2018-11-09 20:08:25 -05:00
|
|
|
#include "audio_core/audio_renderer.h"
|
2021-04-14 19:07:40 -04:00
|
|
|
#include "common/settings.h"
|
2018-07-17 15:42:15 -04:00
|
|
|
#include "core/core.h"
|
2019-05-23 03:55:56 -04:00
|
|
|
#include "core/file_sys/control_metadata.h"
|
|
|
|
#include "core/file_sys/patch_manager.h"
|
2020-07-04 18:49:41 -04:00
|
|
|
#include "core/file_sys/registered_cache.h"
|
2018-12-10 22:17:45 -05:00
|
|
|
#include "core/file_sys/savedata_factory.h"
|
2018-02-02 16:03:40 -05:00
|
|
|
#include "core/hle/ipc_helpers.h"
|
2021-01-31 04:38:57 -05:00
|
|
|
#include "core/hle/kernel/k_event.h"
|
2021-04-24 01:04:28 -04:00
|
|
|
#include "core/hle/kernel/k_process.h"
|
2021-01-30 01:48:06 -05:00
|
|
|
#include "core/hle/kernel/k_readable_event.h"
|
2021-04-17 03:52:53 -04:00
|
|
|
#include "core/hle/kernel/k_transfer_memory.h"
|
2021-01-30 02:51:40 -05:00
|
|
|
#include "core/hle/kernel/k_writable_event.h"
|
2018-11-26 18:34:07 -05:00
|
|
|
#include "core/hle/kernel/kernel.h"
|
2018-10-10 21:49:20 -04:00
|
|
|
#include "core/hle/service/acc/profile_manager.h"
|
2017-10-14 22:50:04 -04:00
|
|
|
#include "core/hle/service/am/am.h"
|
2018-02-02 16:03:40 -05:00
|
|
|
#include "core/hle/service/am/applet_ae.h"
|
2017-10-14 22:50:04 -04:00
|
|
|
#include "core/hle/service/am/applet_oe.h"
|
2018-11-22 15:58:00 -05:00
|
|
|
#include "core/hle/service/am/applets/applets.h"
|
2018-11-22 21:02:57 -05:00
|
|
|
#include "core/hle/service/am/applets/profile_select.h"
|
2018-11-22 15:58:00 -05:00
|
|
|
#include "core/hle/service/am/applets/software_keyboard.h"
|
2018-12-24 16:21:12 -05:00
|
|
|
#include "core/hle/service/am/applets/web_browser.h"
|
2018-07-31 07:01:49 -04:00
|
|
|
#include "core/hle/service/am/idle.h"
|
|
|
|
#include "core/hle/service/am/omm.h"
|
|
|
|
#include "core/hle/service/am/spsm.h"
|
2018-10-21 16:48:58 -04:00
|
|
|
#include "core/hle/service/am/tcap.h"
|
2019-06-28 22:46:51 -04:00
|
|
|
#include "core/hle/service/apm/controller.h"
|
|
|
|
#include "core/hle/service/apm/interface.h"
|
2019-05-01 22:40:51 -04:00
|
|
|
#include "core/hle/service/bcat/backend/backend.h"
|
2018-03-04 13:03:58 -05:00
|
|
|
#include "core/hle/service/filesystem/filesystem.h"
|
2019-05-23 03:55:56 -04:00
|
|
|
#include "core/hle/service/ns/ns.h"
|
2018-02-02 16:03:40 -05:00
|
|
|
#include "core/hle/service/nvflinger/nvflinger.h"
|
2018-08-23 18:31:45 -04:00
|
|
|
#include "core/hle/service/pm/pm.h"
|
2018-04-28 20:30:53 -04:00
|
|
|
#include "core/hle/service/set/set.h"
|
2019-05-23 03:55:56 -04:00
|
|
|
#include "core/hle/service/sm/sm.h"
|
2018-09-18 11:10:16 -04:00
|
|
|
#include "core/hle/service/vi/vi.h"
|
2021-04-17 03:52:53 -04:00
|
|
|
#include "core/memory.h"
|
2017-10-14 22:50:04 -04:00
|
|
|
|
2018-04-19 21:41:44 -04:00
|
|
|
namespace Service::AM {
|
2017-10-14 22:50:04 -04:00
|
|
|
|
2020-04-28 10:49:49 -04:00
|
|
|
constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 2};
|
|
|
|
constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 3};
|
|
|
|
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 503};
|
2018-11-19 14:24:36 -05:00
|
|
|
|
2019-05-01 22:40:51 -04:00
|
|
|
enum class LaunchParameterKind : u32 {
|
|
|
|
ApplicationSpecific = 1,
|
|
|
|
AccountPreselectedUser = 2,
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
|
2018-10-13 13:02:33 -04:00
|
|
|
|
2019-05-01 22:40:51 -04:00
|
|
|
struct LaunchParameterAccountPreselectedUser {
|
2018-10-13 13:02:33 -04:00
|
|
|
u32_le magic;
|
|
|
|
u32_le is_account_selected;
|
|
|
|
u128 current_user;
|
|
|
|
INSERT_PADDING_BYTES(0x70);
|
|
|
|
};
|
2019-05-01 22:40:51 -04:00
|
|
|
static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
|
2018-10-09 21:49:29 -04:00
|
|
|
|
2019-07-11 00:53:55 -04:00
|
|
|
IWindowController::IWindowController(Core::System& system_)
|
2020-11-26 15:19:08 -05:00
|
|
|
: ServiceFramework{system_, "IWindowController"} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-02-02 16:03:40 -05:00
|
|
|
static const FunctionInfo functions[] = {
|
2018-04-10 11:36:00 -04:00
|
|
|
{0, nullptr, "CreateWindow"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{2, nullptr, "GetAppletResourceUserIdOfCallerApplet"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{11, nullptr, "ReleaseForegroundRights"},
|
|
|
|
{12, nullptr, "RejectToChangeIntoBackground"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{20, nullptr, "SetAppletWindowVisibility"},
|
|
|
|
{21, nullptr, "SetAppletGpuTimeSlice"},
|
2018-02-02 16:03:40 -05:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IWindowController::~IWindowController() = default;
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
|
2019-07-11 00:53:55 -04:00
|
|
|
const u64 process_id = system.CurrentProcess()->GetProcessID();
|
2018-12-17 21:01:06 -05:00
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-12-17 21:01:06 -05:00
|
|
|
rb.Push<u64>(process_id);
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
|
2018-07-02 12:13:26 -04:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IAudioController::IAudioController(Core::System& system_)
|
|
|
|
: ServiceFramework{system_, "IAudioController"} {
|
2019-03-17 20:47:03 -04:00
|
|
|
// clang-format off
|
2018-02-22 09:28:15 -05:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
|
2019-03-17 20:47:03 -04:00
|
|
|
{1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
|
|
|
|
{2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
|
2019-03-17 22:39:29 -04:00
|
|
|
{3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
|
2019-03-17 21:09:25 -04:00
|
|
|
{4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
|
2018-02-22 09:28:15 -05:00
|
|
|
};
|
2019-03-17 20:47:03 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-02-22 09:28:15 -05:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IAudioController::~IAudioController() = default;
|
|
|
|
|
2018-02-22 09:28:15 -05:00
|
|
|
void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
|
2019-03-17 20:47:03 -04:00
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const float main_applet_volume_tmp = rp.Pop<float>();
|
|
|
|
const float library_applet_volume_tmp = rp.Pop<float>();
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
|
|
|
|
main_applet_volume_tmp, library_applet_volume_tmp);
|
|
|
|
|
|
|
|
// Ensure the volume values remain within the 0-100% range
|
|
|
|
main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
|
|
|
|
library_applet_volume =
|
|
|
|
std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
|
|
|
|
|
2018-02-22 09:28:15 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
|
2019-03-17 20:47:03 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
|
2018-02-22 09:28:15 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-03-17 20:47:03 -04:00
|
|
|
rb.Push(main_applet_volume);
|
2018-02-22 09:28:15 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
|
2019-03-17 20:47:03 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
|
2018-02-22 09:28:15 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-03-17 20:47:03 -04:00
|
|
|
rb.Push(library_applet_volume);
|
2018-02-22 09:28:15 -05:00
|
|
|
}
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2019-03-17 22:39:29 -04:00
|
|
|
void IAudioController::ChangeMainAppletMasterVolume(Kernel::HLERequestContext& ctx) {
|
|
|
|
struct Parameters {
|
|
|
|
float volume;
|
|
|
|
s64 fade_time_ns;
|
|
|
|
};
|
|
|
|
static_assert(sizeof(Parameters) == 16);
|
|
|
|
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const auto parameters = rp.PopRaw<Parameters>();
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
|
|
|
|
parameters.fade_time_ns);
|
|
|
|
|
|
|
|
main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
|
|
|
|
fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-17 21:09:25 -04:00
|
|
|
void IAudioController::SetTransparentAudioRate(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const float transparent_volume_rate_tmp = rp.Pop<float>();
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
|
|
|
|
|
|
|
|
// Clamp volume range to 0-100%.
|
|
|
|
transparent_volume_rate =
|
|
|
|
std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IDisplayController::IDisplayController(Core::System& system_)
|
|
|
|
: ServiceFramework{system_, "IDisplayController"} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-05-25 22:31:54 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, nullptr, "GetLastForegroundCaptureImage"},
|
|
|
|
{1, nullptr, "UpdateLastForegroundCaptureImage"},
|
|
|
|
{2, nullptr, "GetLastApplicationCaptureImage"},
|
|
|
|
{3, nullptr, "GetCallerAppletCaptureImage"},
|
|
|
|
{4, nullptr, "UpdateCallerAppletCaptureImage"},
|
|
|
|
{5, nullptr, "GetLastForegroundCaptureImageEx"},
|
|
|
|
{6, nullptr, "GetLastApplicationCaptureImageEx"},
|
|
|
|
{7, nullptr, "GetCallerAppletCaptureImageEx"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{8, nullptr, "TakeScreenShotOfOwnLayer"},
|
|
|
|
{9, nullptr, "CopyBetweenCaptureBuffers"},
|
2018-05-25 22:31:54 -04:00
|
|
|
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
|
|
|
|
{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
|
|
|
|
{12, nullptr, "AcquireLastForegroundCaptureBuffer"},
|
|
|
|
{13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
|
|
|
|
{14, nullptr, "AcquireCallerAppletCaptureBuffer"},
|
|
|
|
{15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
|
|
|
|
{16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
|
|
|
|
{17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
|
|
|
|
{18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
|
|
|
|
{20, nullptr, "ClearCaptureBuffer"},
|
|
|
|
{21, nullptr, "ClearAppletTransitionBuffer"},
|
|
|
|
{22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
|
|
|
|
{23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
|
|
|
|
{24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
|
|
|
|
{25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
|
|
|
|
{26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"},
|
|
|
|
{27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{28, nullptr, "TakeScreenShotOfOwnLayerEx"},
|
2018-05-25 22:31:54 -04:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-05-25 22:31:54 -04:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
2018-02-02 16:03:40 -05:00
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IDisplayController::~IDisplayController() = default;
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IDebugFunctions::IDebugFunctions(Core::System& system_)
|
|
|
|
: ServiceFramework{system_, "IDebugFunctions"} {
|
2019-03-21 15:47:59 -04:00
|
|
|
// clang-format off
|
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, nullptr, "NotifyMessageToHomeMenuForDebug"},
|
|
|
|
{1, nullptr, "OpenMainApplication"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{10, nullptr, "PerformSystemButtonPressing"},
|
2019-03-21 15:47:59 -04:00
|
|
|
{20, nullptr, "InvalidateTransitionLayer"},
|
|
|
|
{30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
|
2021-04-07 01:51:15 -04:00
|
|
|
{31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
|
2019-03-21 15:47:59 -04:00
|
|
|
{40, nullptr, "GetAppletResourceUsageInfo"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{100, nullptr, "SetCpuBoostModeForApplet"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{101, nullptr, "CancelCpuBoostModeForApplet"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{110, nullptr, "PushToAppletBoundChannelForDebug"},
|
|
|
|
{111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
|
|
|
|
{120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
|
|
|
|
{121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
|
|
|
|
{122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
|
|
|
|
{130, nullptr, "FriendInvitationSetApplicationParameter"},
|
|
|
|
{131, nullptr, "FriendInvitationClearApplicationParameter"},
|
|
|
|
{132, nullptr, "FriendInvitationPushApplicationParameter"},
|
2021-04-07 01:51:15 -04:00
|
|
|
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
|
2019-03-21 15:47:59 -04:00
|
|
|
};
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IDebugFunctions::~IDebugFunctions() = default;
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_)
|
2021-04-04 03:56:09 -04:00
|
|
|
: ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_},
|
|
|
|
launchable_event{system.Kernel()}, accumulated_suspended_tick_changed_event{system.Kernel()} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-02-02 16:03:40 -05:00
|
|
|
static const FunctionInfo functions[] = {
|
2019-07-06 13:41:38 -04:00
|
|
|
{0, &ISelfController::Exit, "Exit"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{1, &ISelfController::LockExit, "LockExit"},
|
|
|
|
{2, &ISelfController::UnlockExit, "UnlockExit"},
|
2019-03-26 15:12:09 -04:00
|
|
|
{3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
|
|
|
|
{4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
|
2018-02-07 07:11:17 -05:00
|
|
|
{9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
|
2018-02-22 05:04:23 -05:00
|
|
|
{10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
|
|
|
|
{12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
|
|
|
|
{14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{15, nullptr, "SetScreenShotAppletIdentityInfo"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{17, nullptr, "SetControllerFirmwareUpdateSection"},
|
|
|
|
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{20, nullptr, "SetDesirableKeyboardLayout"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{41, nullptr, "IsSystemBufferSharingEnabled"},
|
|
|
|
{42, nullptr, "GetSystemSharedLayerHandle"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{43, nullptr, "GetSystemSharedBufferHandle"},
|
2020-07-05 06:26:07 -04:00
|
|
|
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
|
2018-05-07 11:27:30 -04:00
|
|
|
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{51, nullptr, "ApproveToDisplay"},
|
|
|
|
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
|
|
|
|
{61, nullptr, "SetMediaPlaybackState"},
|
2018-08-17 00:23:08 -04:00
|
|
|
{62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
|
|
|
|
{63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
|
2018-04-11 07:48:56 -04:00
|
|
|
{64, nullptr, "SetInputDetectionSourceSet"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{65, nullptr, "ReportUserIsActive"},
|
|
|
|
{66, nullptr, "GetCurrentIlluminance"},
|
|
|
|
{67, nullptr, "IsIlluminanceAvailable"},
|
2019-07-11 13:02:29 -04:00
|
|
|
{68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
|
2019-07-11 13:32:20 -04:00
|
|
|
{69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{70, nullptr, "ReportMultimediaError"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{71, nullptr, "GetCurrentIlluminanceEx"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{72, nullptr, "SetInputDetectionPolicy"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{80, nullptr, "SetWirelessPriorityMode"},
|
2019-07-06 15:13:34 -04:00
|
|
|
{90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
|
2019-06-16 05:06:33 -04:00
|
|
|
{91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
|
2021-03-30 12:58:27 -04:00
|
|
|
{100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{110, nullptr, "SetApplicationAlbumUserData"},
|
2021-04-07 02:00:19 -04:00
|
|
|
{120, nullptr, "SaveCurrentScreenshot"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{1000, nullptr, "GetDebugStorageChannel"},
|
2018-02-02 16:03:40 -05:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
RegisterHandlers(functions);
|
2018-02-07 07:11:17 -05:00
|
|
|
|
2021-04-09 19:56:11 -04:00
|
|
|
Kernel::KAutoObject::Create(std::addressof(launchable_event));
|
|
|
|
|
2021-04-04 03:56:09 -04:00
|
|
|
launchable_event.Initialize("ISelfController:LaunchableEvent");
|
2019-06-16 05:06:33 -04:00
|
|
|
|
2019-07-06 16:52:05 -04:00
|
|
|
// This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
|
|
|
|
// called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
|
|
|
|
// ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
|
|
|
|
// suspended if the event has previously been created by a call to
|
|
|
|
// GetAccumulatedSuspendedTickChangedEvent.
|
2021-04-04 03:56:09 -04:00
|
|
|
|
2021-04-09 19:56:11 -04:00
|
|
|
Kernel::KAutoObject::Create(std::addressof(accumulated_suspended_tick_changed_event));
|
2021-04-04 03:56:09 -04:00
|
|
|
accumulated_suspended_tick_changed_event.Initialize(
|
|
|
|
"ISelfController:AccumulatedSuspendedTickChangedEvent");
|
2021-04-10 05:34:26 -04:00
|
|
|
accumulated_suspended_tick_changed_event.GetWritableEvent().Signal();
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
ISelfController::~ISelfController() = default;
|
|
|
|
|
2019-07-06 13:41:38 -04:00
|
|
|
void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
system.Shutdown();
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
|
2019-07-06 13:42:06 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
system.SetExitLock(true);
|
2018-02-02 16:03:40 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
|
2019-07-06 13:42:06 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
system.SetExitLock(false);
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 15:12:09 -04:00
|
|
|
void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) {
|
|
|
|
++num_fatal_sections_entered;
|
|
|
|
LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called.");
|
|
|
|
|
|
|
|
// Entry and exit of fatal sections must be balanced.
|
|
|
|
if (num_fatal_sections_entered == 0) {
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(ResultCode{ErrorModule::AM, 512});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
--num_fatal_sections_entered;
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2021-04-10 05:34:26 -04:00
|
|
|
launchable_event.GetWritableEvent().Signal();
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
2018-02-02 16:03:40 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-04 03:56:09 -04:00
|
|
|
rb.PushCopyObjects(launchable_event.GetReadableEvent());
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2018-02-22 05:04:23 -05:00
|
|
|
void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
|
2020-07-31 10:44:14 -04:00
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const auto permission = rp.PopEnum<ScreenshotPermission>();
|
|
|
|
LOG_DEBUG(Service_AM, "called, permission={}", permission);
|
|
|
|
|
|
|
|
screenshot_permission = permission;
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-02-22 05:04:23 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
|
|
|
|
bool flag = rp.Pop<bool>();
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
|
2018-02-02 16:03:40 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
bool flag = rp.Pop<bool>();
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
|
2018-02-02 16:03:40 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
|
|
|
|
// Takes 3 input u8s with each field located immediately after the previous
|
|
|
|
// u8, these are bool flags. No output.
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
|
|
|
|
struct FocusHandlingModeParams {
|
|
|
|
u8 unknown0;
|
|
|
|
u8 unknown1;
|
|
|
|
u8 unknown2;
|
|
|
|
};
|
2019-04-04 12:56:04 -04:00
|
|
|
const auto flags = rp.PopRaw<FocusHandlingModeParams>();
|
|
|
|
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
|
|
|
|
flags.unknown0, flags.unknown1, flags.unknown2);
|
2019-03-26 14:54:03 -04:00
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
|
|
|
|
// Takes 3 input u8s with each field located immediately after the previous
|
|
|
|
// u8, these are bool flags. No output.
|
|
|
|
IPC::RequestParser rp{ctx};
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
bool enabled = rp.Pop<bool>();
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
|
2018-02-07 07:11:17 -05:00
|
|
|
|
2019-03-26 14:54:03 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2018-02-07 07:11:17 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-11-29 09:14:12 -05:00
|
|
|
}
|
2018-02-07 07:11:17 -05:00
|
|
|
|
2020-06-26 20:32:26 -04:00
|
|
|
void ISelfController::SetAlbumImageOrientation(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-08-08 00:40:46 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
2019-02-05 16:20:04 -05:00
|
|
|
|
2018-11-17 09:05:55 -05:00
|
|
|
// TODO(Subv): Find out how AM determines the display to use, for now just
|
|
|
|
// create the layer in the Default display.
|
2020-11-24 17:31:58 -05:00
|
|
|
const auto display_id = nvflinger.OpenDisplay("Default");
|
|
|
|
const auto layer_id = nvflinger.CreateLayer(*display_id);
|
2018-02-02 16:03:40 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-02-05 16:20:04 -05:00
|
|
|
rb.Push(*layer_id);
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2020-07-05 06:26:07 -04:00
|
|
|
void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
// TODO(Subv): Find out how AM determines the display to use, for now just
|
|
|
|
// create the layer in the Default display.
|
|
|
|
// This calls nn::vi::CreateRecordingLayer() which creates another layer.
|
|
|
|
// Currently we do not support more than 1 layer per display, output 1 layer id for now.
|
|
|
|
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
|
|
|
|
// side effects.
|
|
|
|
// TODO: Support multiple layers
|
2020-11-24 17:31:58 -05:00
|
|
|
const auto display_id = nvflinger.OpenDisplay("Default");
|
|
|
|
const auto layer_id = nvflinger.CreateLayer(*display_id);
|
2020-07-05 06:26:07 -04:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push(*layer_id);
|
|
|
|
}
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-08-17 00:23:08 -04:00
|
|
|
void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
idle_time_detection_extension = rp.Pop<u32>();
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
|
|
|
|
idle_time_detection_extension);
|
|
|
|
|
2018-08-17 00:23:08 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-08-17 00:23:08 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<u32>(idle_time_detection_extension);
|
|
|
|
}
|
|
|
|
|
2019-07-11 13:02:29 -04:00
|
|
|
void ISelfController::SetAutoSleepDisabled(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
is_auto_sleep_disabled = rp.Pop<bool>();
|
|
|
|
|
|
|
|
// On the system itself, if the previous state of is_auto_sleep_disabled
|
|
|
|
// differed from the current value passed in, it'd signify the internal
|
|
|
|
// window manager to update (and also increment some statistics like update counts)
|
|
|
|
//
|
|
|
|
// It'd also indicate this change to an idle handling context.
|
|
|
|
//
|
|
|
|
// However, given we're emulating this behavior, most of this can be ignored
|
|
|
|
// and it's sufficient to simply set the member variable for querying via
|
|
|
|
// IsAutoSleepDisabled().
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-07-11 13:32:20 -04:00
|
|
|
void ISelfController::IsAutoSleepDisabled(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called.");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push(is_auto_sleep_disabled);
|
|
|
|
}
|
|
|
|
|
2019-07-06 15:13:34 -04:00
|
|
|
void ISelfController::GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called.");
|
|
|
|
|
|
|
|
// This command returns the total number of system ticks since ISelfController creation
|
|
|
|
// where the game was suspended. Since Yuzu doesn't implement game suspension, this command
|
|
|
|
// can just always return 0 ticks.
|
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<u64>(0);
|
|
|
|
}
|
|
|
|
|
2019-06-16 05:06:33 -04:00
|
|
|
void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx) {
|
2019-07-06 15:13:34 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called.");
|
2019-06-16 05:06:33 -04:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-04 03:56:09 -04:00
|
|
|
rb.PushCopyObjects(accumulated_suspended_tick_changed_event.GetReadableEvent());
|
2019-06-16 05:06:33 -04:00
|
|
|
}
|
|
|
|
|
2021-03-30 12:58:27 -04:00
|
|
|
void ISelfController::SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
|
|
|
|
// This service call sets an internal flag whether a notification is shown when an image is
|
|
|
|
// captured. Currently we do not support capturing images via the capture button, so this can be
|
|
|
|
// stubbed for now.
|
|
|
|
const bool album_image_taken_notification_enabled = rp.Pop<bool>();
|
|
|
|
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
|
|
|
|
album_image_taken_notification_enabled);
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2021-04-04 03:56:09 -04:00
|
|
|
AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel)
|
|
|
|
: on_new_message{kernel}, on_operation_mode_changed{kernel} {
|
2021-04-09 19:56:11 -04:00
|
|
|
|
|
|
|
Kernel::KAutoObject::Create(std::addressof(on_new_message));
|
|
|
|
Kernel::KAutoObject::Create(std::addressof(on_operation_mode_changed));
|
|
|
|
|
2021-04-04 03:56:09 -04:00
|
|
|
on_new_message.Initialize("AMMessageQueue:OnMessageReceived");
|
|
|
|
on_operation_mode_changed.Initialize("AMMessageQueue:OperationModeChanged");
|
2018-11-07 02:01:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
AppletMessageQueue::~AppletMessageQueue() = default;
|
|
|
|
|
2021-04-10 05:34:26 -04:00
|
|
|
Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
|
|
|
|
return on_new_message.GetReadableEvent();
|
2018-11-07 02:01:33 -05:00
|
|
|
}
|
|
|
|
|
2021-04-10 05:34:26 -04:00
|
|
|
Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
|
|
|
|
return on_operation_mode_changed.GetReadableEvent();
|
2018-11-07 02:01:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
|
|
|
messages.push(msg);
|
2021-04-10 05:34:26 -04:00
|
|
|
on_new_message.GetWritableEvent().Signal();
|
2018-11-07 02:01:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
|
|
|
if (messages.empty()) {
|
2021-04-10 05:34:26 -04:00
|
|
|
on_new_message.GetWritableEvent().Clear();
|
2018-11-07 02:01:33 -05:00
|
|
|
return AppletMessage::NoMessage;
|
|
|
|
}
|
|
|
|
auto msg = messages.front();
|
|
|
|
messages.pop();
|
|
|
|
if (messages.empty()) {
|
2021-04-10 05:34:26 -04:00
|
|
|
on_new_message.GetWritableEvent().Clear();
|
2018-11-07 02:01:33 -05:00
|
|
|
}
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t AppletMessageQueue::GetMessageCount() const {
|
|
|
|
return messages.size();
|
|
|
|
}
|
|
|
|
|
2021-04-17 09:19:02 -04:00
|
|
|
void AppletMessageQueue::RequestExit() {
|
|
|
|
PushMessage(AppletMessage::ExitRequested);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppletMessageQueue::FocusStateChanged() {
|
|
|
|
PushMessage(AppletMessage::FocusStateChanged);
|
|
|
|
}
|
|
|
|
|
2018-11-07 02:01:33 -05:00
|
|
|
void AppletMessageQueue::OperationModeChanged() {
|
|
|
|
PushMessage(AppletMessage::OperationModeChanged);
|
|
|
|
PushMessage(AppletMessage::PerformanceModeChanged);
|
2021-04-10 05:34:26 -04:00
|
|
|
on_operation_mode_changed.GetWritableEvent().Signal();
|
2018-11-07 02:01:33 -05:00
|
|
|
}
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
|
|
|
std::shared_ptr<AppletMessageQueue> msg_queue_)
|
|
|
|
: ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-02-02 16:03:40 -05:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
|
|
|
|
{1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{2, nullptr, "GetThisAppletKind"},
|
|
|
|
{3, nullptr, "AllowToEnterSleep"},
|
|
|
|
{4, nullptr, "DisallowToEnterSleep"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
|
|
|
|
{6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{7, nullptr, "GetCradleStatus"},
|
2018-08-23 18:31:45 -04:00
|
|
|
{8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{10, nullptr, "RequestToAcquireSleepLock"},
|
|
|
|
{11, nullptr, "ReleaseSleepLock"},
|
|
|
|
{12, nullptr, "ReleaseSleepLockTransiently"},
|
|
|
|
{13, nullptr, "GetAcquiredSleepLockEvent"},
|
2021-04-07 01:49:13 -04:00
|
|
|
{14, nullptr, "GetWakeupCount"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{20, nullptr, "PushToGeneralChannel"},
|
|
|
|
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
|
|
|
|
{31, nullptr, "GetReaderLockAccessorEx"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{32, nullptr, "GetWriterLockAccessorEx"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{40, nullptr, "GetCradleFwVersion"},
|
2020-03-26 10:31:45 -04:00
|
|
|
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
|
|
|
|
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
|
2020-02-27 11:49:23 -05:00
|
|
|
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
|
2021-01-24 08:34:01 -05:00
|
|
|
{53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
|
2020-03-26 10:31:45 -04:00
|
|
|
{54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
|
2021-04-07 01:49:13 -04:00
|
|
|
{59, nullptr, "SetVrPositionForDebug"},
|
2018-09-18 11:10:16 -04:00
|
|
|
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{62, nullptr, "GetHdcpAuthenticationState"},
|
|
|
|
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{64, nullptr, "SetTvPowerStateMatchingMode"},
|
|
|
|
{65, nullptr, "GetApplicationIdByContentActionName"},
|
2019-06-28 22:46:51 -04:00
|
|
|
{66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{67, nullptr, "CancelCpuBoostMode"},
|
2021-04-07 01:49:13 -04:00
|
|
|
{68, nullptr, "GetBuiltInDisplayType"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{80, nullptr, "PerformSystemButtonPressingIfInFocus"},
|
|
|
|
{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
|
|
|
|
{91, nullptr, "GetCurrentPerformanceConfiguration"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
|
2021-04-07 01:49:13 -04:00
|
|
|
{110, nullptr, "OpenMyGpuErrorHandler"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{200, nullptr, "GetOperationModeSystemInfo"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{300, nullptr, "GetSettingsPlatformRegion"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{400, nullptr, "ActivateMigrationService"},
|
|
|
|
{401, nullptr, "DeactivateMigrationService"},
|
2021-04-07 01:49:13 -04:00
|
|
|
{500, nullptr, "DisableSleepTillShutdown"},
|
|
|
|
{501, nullptr, "SuppressDisablingSleepTemporarily"},
|
|
|
|
{502, nullptr, "IsSleepEnabled"},
|
|
|
|
{503, nullptr, "IsDisablingSleepSuppressed"},
|
2021-04-23 22:46:25 -04:00
|
|
|
{900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
|
2018-02-02 16:03:40 -05:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
ICommonStateGetter::~ICommonStateGetter() = default;
|
|
|
|
|
2018-08-23 18:31:45 -04:00
|
|
|
void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-08-23 18:31:45 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
|
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-01-02 09:00:05 -05:00
|
|
|
rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent());
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2019-01-03 21:11:17 -05:00
|
|
|
const auto message = msg_queue->PopMessage();
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
2019-01-03 21:11:17 -05:00
|
|
|
|
|
|
|
if (message == AppletMessageQueue::AppletMessage::NoMessage) {
|
|
|
|
LOG_ERROR(Service_AM, "Message queue is empty");
|
|
|
|
rb.Push(ERR_NO_MESSAGES);
|
|
|
|
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
|
|
|
|
return;
|
|
|
|
}
|
2020-02-27 11:49:23 -05:00
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-01-03 21:11:17 -05:00
|
|
|
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push(static_cast<u8>(FocusState::InFocus));
|
|
|
|
}
|
|
|
|
|
2020-03-26 10:31:45 -04:00
|
|
|
void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) {
|
2020-04-29 07:48:58 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
2020-03-26 10:31:45 -04:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-04-29 07:48:58 -04:00
|
|
|
rb.Push(vr_mode_state);
|
2020-03-26 10:31:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
2020-04-29 07:48:58 -04:00
|
|
|
vr_mode_state = rp.Pop<bool>();
|
2020-03-26 10:31:45 -04:00
|
|
|
|
2020-04-29 07:48:58 -04:00
|
|
|
LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off");
|
2020-03-26 10:31:45 -04:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2020-04-29 07:48:58 -04:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-03-26 10:31:45 -04:00
|
|
|
}
|
|
|
|
|
2020-02-27 11:49:23 -05:00
|
|
|
void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
|
|
|
|
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
|
|
|
|
is_lcd_backlight_off_enabled);
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2021-01-24 08:34:01 -05:00
|
|
|
void ICommonStateGetter::BeginVrModeEx(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-03-26 10:31:45 -04:00
|
|
|
void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-08-16 17:20:54 -04:00
|
|
|
void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-08-16 17:20:54 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-11-07 02:01:33 -05:00
|
|
|
rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
|
2018-08-16 17:20:54 -04:00
|
|
|
}
|
|
|
|
|
2018-09-18 11:10:16 -04:00
|
|
|
void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-09-18 11:10:16 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
2020-09-28 10:00:15 -04:00
|
|
|
if (Settings::values.use_docked_mode.GetValue()) {
|
2018-11-16 02:07:42 -05:00
|
|
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
|
configuration: implement per-game configurations (#4098)
* Switch game settings to use a pointer
In order to add full per-game settings, we need to be able to tell yuzu to switch
to using either the global or game configuration. Using a pointer makes it easier
to switch.
* configuration: add new UI without changing existing funcitonality
The new UI also adds General, System, Graphics, Advanced Graphics,
and Audio tabs, but as yet they do nothing. This commit keeps yuzu
to the same functionality as originally branched.
* configuration: Rename files
These weren't included in the last commit. Now they are.
* configuration: setup global configuration checkbox
Global config checkbox now enables/disables the appropriate tabs in the game
properties dialog. The use global configuration setting is now saved to the
config, defaulting to true. This also addresses some changes requested in the PR.
* configuration: swap to per-game config memory for properties dialog
Does not set memory going in-game. Swaps to game values when opening the
properties dialog, then swaps back when closing it. Uses a `memcpy` to swap.
Also implements saving config files, limited to certain groups of configurations
so as to not risk setting unsafe configurations.
* configuration: change config interfaces to use config-specific pointers
When a game is booted, we need to be able to open the configuration dialogs
without changing the settings pointer in the game's emualtion. A new pointer
specific to just the configuration dialogs can be used to separate changes
to just those config dialogs without affecting the emulation.
* configuration: boot a game using per-game settings
Swaps values where needed to boot a game.
* configuration: user correct config during emulation
Creates a new pointer specifically for modifying the configuration while
emulation is in progress. Both the regular configuration dialog and the game
properties dialog now use the pointer Settings::config_values to focus edits to
the correct struct.
* settings: split Settings::values into two different structs
By splitting the settings into two mutually exclusive structs, it becomes easier,
as a developer, to determine how to use the Settings structs after per-game
configurations is merged. Other benefits include only duplicating the required
settings in memory.
* settings: move use_docked_mode to Controls group
`use_docked_mode` is set in the input settings and cannot be accessed from the
system settings. Grouping it with system settings causes it to be saved with
per-game settings, which may make transferring configs more difficult later on,
especially since docked mode cannot be set from within the game properties
dialog.
* configuration: Fix the other yuzu executables and a regression
In main.cpp, we have to get the title ID before the ROM is loaded, else the
renderer will reflect only the global settings and now the user's game specific
settings.
* settings: use a template to duplicate memory for each setting
Replaces the type of each variable in the Settings::Values struct with a new
class that allows basic data reading and writing. The new struct
Settings::Setting duplicates the data in memory and can manage global overrides
per each setting.
* configuration: correct add-ons config and swap settings when apropriate
Any add-ons interaction happens directly through the global values struct.
Swapping bewteen structs now also includes copying the necessary global configs
that cannot be changed nor saved in per-game settings. General and System config
menus now update based on whether it is viewing the global or per-game settings.
* settings: restore old values struct
No longer needed with the Settings::Setting class template.
* configuration: implement hierarchical game properties dialog
This sets the apropriate global or local data in each setting.
* clang format
* clang format take 2
can the docker container save this?
* address comments and style issues
* config: read and write settings with global awareness
Adds new functions to read and write settings while keeping the global state in
focus. Files now generated per-game are much smaller since often they only need
address the global state.
* settings: restore global state when necessary
Upon closing a game or the game properties dialog, we need to restore all global
settings to the original global state so that we can properly open the
configuration dialog or boot a different game.
* configuration: guard setting values incorrectly
This disables setting values while a game is running if the setting is
overwritten by a per game setting.
* config: don't write local settings in the global config
Simple guards to prevent writing the wrong settings in the wrong files.
* configuration: add comments, assume less, and clang format
No longer assumes that a disabled UI element means the global state is turned
off, instead opting to directly answer that question. Still however assumes a
game is running if it is in that state.
* configuration: fix a logic error
Should not be negated
* restore settings' global state regardless of accept/cancel
Fixes loading a properties dialog and causing the global config dialog to show
local settings.
* fix more logic errors
Fixed the frame limit would set the global setting from the game properties
dialog. Also strengthened the Settings::Setting member variables and simplified
the logic in config reading (ReadSettingGlobal).
* fix another logic error
In my efforts to guard RestoreGlobalState, I accidentally negated the IsPowered
condition.
* configure_audio: set toggle_stretched_audio to tristate
* fixed custom rtc and rng seed overwriting the global value
* clang format
* rebased
* clang format take 4
* address my own review
Basically revert unintended changes
* settings: literal instead of casting
"No need to cast, use 1U instead"
Thanks, Morph!
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
* Revert "settings: literal instead of casting
"
This reverts commit 95e992a87c898f3e882ffdb415bb0ef9f80f613f.
* main: fix status buttons reporting wrong settings after stop emulation
* settings: Log UseDockedMode in the Controls group
This should have happened when use_docked_mode was moved over to the controls group
internally. This just reflects this in the log.
* main: load settings if the file has a title id
In other words, don't exit if the loader has trouble getting a title id.
* use a zero
* settings: initalize resolution factor with constructor instead of casting
* Revert "settings: initalize resolution factor with constructor instead of casting"
This reverts commit 54c35ecb46a29953842614620f9b7de1aa9d5dc8.
* configure_graphics: guard device selector when Vulkan is global
Prevents the user from editing the device selector if Vulkan is the global
renderer backend. Also resets the vulkan_device variable when the users
switches back-and-forth between global and Vulkan.
* address reviewer concerns
Changes function variables to const wherever they don't need to be changed. Sets Settings::Setting to final as it should not be inherited from. Sets ConfigurationShared::use_global_text to static.
Co-Authored-By: VolcaEM <volcaem@users.noreply.github.com>
* main: load per-game settings after LoadROM
This prevents `Restart Emulation` from restoring the global settings *after* the per-game settings were applied. Thanks to BSoDGamingYT for finding this bug.
* Revert "main: load per-game settings after LoadROM"
This reverts commit 9d0d48c52d2dcf3bfb1806cc8fa7d5a271a8a804.
* main: only restore global settings when necessary
Loading the per-game settings cannot happen after the ROM is loaded, so we have to specify when to restore the global state. Again thanks to BSoD for finding the bug.
* configuration_shared: address reviewer concerns except operator overrides
Dropping operator override usage in next commit.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
* settings: Drop operator overrides from Setting template
Requires using GetValue and SetValue explicitly. Also reverts a change that broke title ID formatting in the game properties dialog.
* complete rebase
* configuration_shared: translate "Use global configuration"
Uses ConfigurePerGame to do so, since its usage, at least as of now, corresponds with ConfigurationShared.
* configure_per_game: address reviewer concern
As far as I understand, it prevents the program from unnecessarily copying strings.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
Co-authored-by: VolcaEM <volcaem@users.noreply.github.com>
Co-authored-by: LC <lioncash@users.noreply.github.com>
2020-07-09 22:42:09 -04:00
|
|
|
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
|
2018-11-16 02:07:42 -05:00
|
|
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
|
configuration: implement per-game configurations (#4098)
* Switch game settings to use a pointer
In order to add full per-game settings, we need to be able to tell yuzu to switch
to using either the global or game configuration. Using a pointer makes it easier
to switch.
* configuration: add new UI without changing existing funcitonality
The new UI also adds General, System, Graphics, Advanced Graphics,
and Audio tabs, but as yet they do nothing. This commit keeps yuzu
to the same functionality as originally branched.
* configuration: Rename files
These weren't included in the last commit. Now they are.
* configuration: setup global configuration checkbox
Global config checkbox now enables/disables the appropriate tabs in the game
properties dialog. The use global configuration setting is now saved to the
config, defaulting to true. This also addresses some changes requested in the PR.
* configuration: swap to per-game config memory for properties dialog
Does not set memory going in-game. Swaps to game values when opening the
properties dialog, then swaps back when closing it. Uses a `memcpy` to swap.
Also implements saving config files, limited to certain groups of configurations
so as to not risk setting unsafe configurations.
* configuration: change config interfaces to use config-specific pointers
When a game is booted, we need to be able to open the configuration dialogs
without changing the settings pointer in the game's emualtion. A new pointer
specific to just the configuration dialogs can be used to separate changes
to just those config dialogs without affecting the emulation.
* configuration: boot a game using per-game settings
Swaps values where needed to boot a game.
* configuration: user correct config during emulation
Creates a new pointer specifically for modifying the configuration while
emulation is in progress. Both the regular configuration dialog and the game
properties dialog now use the pointer Settings::config_values to focus edits to
the correct struct.
* settings: split Settings::values into two different structs
By splitting the settings into two mutually exclusive structs, it becomes easier,
as a developer, to determine how to use the Settings structs after per-game
configurations is merged. Other benefits include only duplicating the required
settings in memory.
* settings: move use_docked_mode to Controls group
`use_docked_mode` is set in the input settings and cannot be accessed from the
system settings. Grouping it with system settings causes it to be saved with
per-game settings, which may make transferring configs more difficult later on,
especially since docked mode cannot be set from within the game properties
dialog.
* configuration: Fix the other yuzu executables and a regression
In main.cpp, we have to get the title ID before the ROM is loaded, else the
renderer will reflect only the global settings and now the user's game specific
settings.
* settings: use a template to duplicate memory for each setting
Replaces the type of each variable in the Settings::Values struct with a new
class that allows basic data reading and writing. The new struct
Settings::Setting duplicates the data in memory and can manage global overrides
per each setting.
* configuration: correct add-ons config and swap settings when apropriate
Any add-ons interaction happens directly through the global values struct.
Swapping bewteen structs now also includes copying the necessary global configs
that cannot be changed nor saved in per-game settings. General and System config
menus now update based on whether it is viewing the global or per-game settings.
* settings: restore old values struct
No longer needed with the Settings::Setting class template.
* configuration: implement hierarchical game properties dialog
This sets the apropriate global or local data in each setting.
* clang format
* clang format take 2
can the docker container save this?
* address comments and style issues
* config: read and write settings with global awareness
Adds new functions to read and write settings while keeping the global state in
focus. Files now generated per-game are much smaller since often they only need
address the global state.
* settings: restore global state when necessary
Upon closing a game or the game properties dialog, we need to restore all global
settings to the original global state so that we can properly open the
configuration dialog or boot a different game.
* configuration: guard setting values incorrectly
This disables setting values while a game is running if the setting is
overwritten by a per game setting.
* config: don't write local settings in the global config
Simple guards to prevent writing the wrong settings in the wrong files.
* configuration: add comments, assume less, and clang format
No longer assumes that a disabled UI element means the global state is turned
off, instead opting to directly answer that question. Still however assumes a
game is running if it is in that state.
* configuration: fix a logic error
Should not be negated
* restore settings' global state regardless of accept/cancel
Fixes loading a properties dialog and causing the global config dialog to show
local settings.
* fix more logic errors
Fixed the frame limit would set the global setting from the game properties
dialog. Also strengthened the Settings::Setting member variables and simplified
the logic in config reading (ReadSettingGlobal).
* fix another logic error
In my efforts to guard RestoreGlobalState, I accidentally negated the IsPowered
condition.
* configure_audio: set toggle_stretched_audio to tristate
* fixed custom rtc and rng seed overwriting the global value
* clang format
* rebased
* clang format take 4
* address my own review
Basically revert unintended changes
* settings: literal instead of casting
"No need to cast, use 1U instead"
Thanks, Morph!
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
* Revert "settings: literal instead of casting
"
This reverts commit 95e992a87c898f3e882ffdb415bb0ef9f80f613f.
* main: fix status buttons reporting wrong settings after stop emulation
* settings: Log UseDockedMode in the Controls group
This should have happened when use_docked_mode was moved over to the controls group
internally. This just reflects this in the log.
* main: load settings if the file has a title id
In other words, don't exit if the loader has trouble getting a title id.
* use a zero
* settings: initalize resolution factor with constructor instead of casting
* Revert "settings: initalize resolution factor with constructor instead of casting"
This reverts commit 54c35ecb46a29953842614620f9b7de1aa9d5dc8.
* configure_graphics: guard device selector when Vulkan is global
Prevents the user from editing the device selector if Vulkan is the global
renderer backend. Also resets the vulkan_device variable when the users
switches back-and-forth between global and Vulkan.
* address reviewer concerns
Changes function variables to const wherever they don't need to be changed. Sets Settings::Setting to final as it should not be inherited from. Sets ConfigurationShared::use_global_text to static.
Co-Authored-By: VolcaEM <volcaem@users.noreply.github.com>
* main: load per-game settings after LoadROM
This prevents `Restart Emulation` from restoring the global settings *after* the per-game settings were applied. Thanks to BSoDGamingYT for finding this bug.
* Revert "main: load per-game settings after LoadROM"
This reverts commit 9d0d48c52d2dcf3bfb1806cc8fa7d5a271a8a804.
* main: only restore global settings when necessary
Loading the per-game settings cannot happen after the ROM is loaded, so we have to specify when to restore the global state. Again thanks to BSoD for finding the bug.
* configuration_shared: address reviewer concerns except operator overrides
Dropping operator override usage in next commit.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
* settings: Drop operator overrides from Setting template
Requires using GetValue and SetValue explicitly. Also reverts a change that broke title ID formatting in the game properties dialog.
* complete rebase
* configuration_shared: translate "Use global configuration"
Uses ConfigurePerGame to do so, since its usage, at least as of now, corresponds with ConfigurationShared.
* configure_per_game: address reviewer concern
As far as I understand, it prevents the program from unnecessarily copying strings.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
Co-authored-by: VolcaEM <volcaem@users.noreply.github.com>
Co-authored-by: LC <lioncash@users.noreply.github.com>
2020-07-09 22:42:09 -04:00
|
|
|
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
|
2018-09-18 11:10:16 -04:00
|
|
|
} else {
|
2018-11-16 02:07:42 -05:00
|
|
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
|
configuration: implement per-game configurations (#4098)
* Switch game settings to use a pointer
In order to add full per-game settings, we need to be able to tell yuzu to switch
to using either the global or game configuration. Using a pointer makes it easier
to switch.
* configuration: add new UI without changing existing funcitonality
The new UI also adds General, System, Graphics, Advanced Graphics,
and Audio tabs, but as yet they do nothing. This commit keeps yuzu
to the same functionality as originally branched.
* configuration: Rename files
These weren't included in the last commit. Now they are.
* configuration: setup global configuration checkbox
Global config checkbox now enables/disables the appropriate tabs in the game
properties dialog. The use global configuration setting is now saved to the
config, defaulting to true. This also addresses some changes requested in the PR.
* configuration: swap to per-game config memory for properties dialog
Does not set memory going in-game. Swaps to game values when opening the
properties dialog, then swaps back when closing it. Uses a `memcpy` to swap.
Also implements saving config files, limited to certain groups of configurations
so as to not risk setting unsafe configurations.
* configuration: change config interfaces to use config-specific pointers
When a game is booted, we need to be able to open the configuration dialogs
without changing the settings pointer in the game's emualtion. A new pointer
specific to just the configuration dialogs can be used to separate changes
to just those config dialogs without affecting the emulation.
* configuration: boot a game using per-game settings
Swaps values where needed to boot a game.
* configuration: user correct config during emulation
Creates a new pointer specifically for modifying the configuration while
emulation is in progress. Both the regular configuration dialog and the game
properties dialog now use the pointer Settings::config_values to focus edits to
the correct struct.
* settings: split Settings::values into two different structs
By splitting the settings into two mutually exclusive structs, it becomes easier,
as a developer, to determine how to use the Settings structs after per-game
configurations is merged. Other benefits include only duplicating the required
settings in memory.
* settings: move use_docked_mode to Controls group
`use_docked_mode` is set in the input settings and cannot be accessed from the
system settings. Grouping it with system settings causes it to be saved with
per-game settings, which may make transferring configs more difficult later on,
especially since docked mode cannot be set from within the game properties
dialog.
* configuration: Fix the other yuzu executables and a regression
In main.cpp, we have to get the title ID before the ROM is loaded, else the
renderer will reflect only the global settings and now the user's game specific
settings.
* settings: use a template to duplicate memory for each setting
Replaces the type of each variable in the Settings::Values struct with a new
class that allows basic data reading and writing. The new struct
Settings::Setting duplicates the data in memory and can manage global overrides
per each setting.
* configuration: correct add-ons config and swap settings when apropriate
Any add-ons interaction happens directly through the global values struct.
Swapping bewteen structs now also includes copying the necessary global configs
that cannot be changed nor saved in per-game settings. General and System config
menus now update based on whether it is viewing the global or per-game settings.
* settings: restore old values struct
No longer needed with the Settings::Setting class template.
* configuration: implement hierarchical game properties dialog
This sets the apropriate global or local data in each setting.
* clang format
* clang format take 2
can the docker container save this?
* address comments and style issues
* config: read and write settings with global awareness
Adds new functions to read and write settings while keeping the global state in
focus. Files now generated per-game are much smaller since often they only need
address the global state.
* settings: restore global state when necessary
Upon closing a game or the game properties dialog, we need to restore all global
settings to the original global state so that we can properly open the
configuration dialog or boot a different game.
* configuration: guard setting values incorrectly
This disables setting values while a game is running if the setting is
overwritten by a per game setting.
* config: don't write local settings in the global config
Simple guards to prevent writing the wrong settings in the wrong files.
* configuration: add comments, assume less, and clang format
No longer assumes that a disabled UI element means the global state is turned
off, instead opting to directly answer that question. Still however assumes a
game is running if it is in that state.
* configuration: fix a logic error
Should not be negated
* restore settings' global state regardless of accept/cancel
Fixes loading a properties dialog and causing the global config dialog to show
local settings.
* fix more logic errors
Fixed the frame limit would set the global setting from the game properties
dialog. Also strengthened the Settings::Setting member variables and simplified
the logic in config reading (ReadSettingGlobal).
* fix another logic error
In my efforts to guard RestoreGlobalState, I accidentally negated the IsPowered
condition.
* configure_audio: set toggle_stretched_audio to tristate
* fixed custom rtc and rng seed overwriting the global value
* clang format
* rebased
* clang format take 4
* address my own review
Basically revert unintended changes
* settings: literal instead of casting
"No need to cast, use 1U instead"
Thanks, Morph!
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
* Revert "settings: literal instead of casting
"
This reverts commit 95e992a87c898f3e882ffdb415bb0ef9f80f613f.
* main: fix status buttons reporting wrong settings after stop emulation
* settings: Log UseDockedMode in the Controls group
This should have happened when use_docked_mode was moved over to the controls group
internally. This just reflects this in the log.
* main: load settings if the file has a title id
In other words, don't exit if the loader has trouble getting a title id.
* use a zero
* settings: initalize resolution factor with constructor instead of casting
* Revert "settings: initalize resolution factor with constructor instead of casting"
This reverts commit 54c35ecb46a29953842614620f9b7de1aa9d5dc8.
* configure_graphics: guard device selector when Vulkan is global
Prevents the user from editing the device selector if Vulkan is the global
renderer backend. Also resets the vulkan_device variable when the users
switches back-and-forth between global and Vulkan.
* address reviewer concerns
Changes function variables to const wherever they don't need to be changed. Sets Settings::Setting to final as it should not be inherited from. Sets ConfigurationShared::use_global_text to static.
Co-Authored-By: VolcaEM <volcaem@users.noreply.github.com>
* main: load per-game settings after LoadROM
This prevents `Restart Emulation` from restoring the global settings *after* the per-game settings were applied. Thanks to BSoDGamingYT for finding this bug.
* Revert "main: load per-game settings after LoadROM"
This reverts commit 9d0d48c52d2dcf3bfb1806cc8fa7d5a271a8a804.
* main: only restore global settings when necessary
Loading the per-game settings cannot happen after the ROM is loaded, so we have to specify when to restore the global state. Again thanks to BSoD for finding the bug.
* configuration_shared: address reviewer concerns except operator overrides
Dropping operator override usage in next commit.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
* settings: Drop operator overrides from Setting template
Requires using GetValue and SetValue explicitly. Also reverts a change that broke title ID formatting in the game properties dialog.
* complete rebase
* configuration_shared: translate "Use global configuration"
Uses ConfigurePerGame to do so, since its usage, at least as of now, corresponds with ConfigurationShared.
* configure_per_game: address reviewer concern
As far as I understand, it prevents the program from unnecessarily copying strings.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
Co-authored-by: VolcaEM <volcaem@users.noreply.github.com>
Co-authored-by: LC <lioncash@users.noreply.github.com>
2020-07-09 22:42:09 -04:00
|
|
|
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
|
2018-11-16 02:07:42 -05:00
|
|
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
|
configuration: implement per-game configurations (#4098)
* Switch game settings to use a pointer
In order to add full per-game settings, we need to be able to tell yuzu to switch
to using either the global or game configuration. Using a pointer makes it easier
to switch.
* configuration: add new UI without changing existing funcitonality
The new UI also adds General, System, Graphics, Advanced Graphics,
and Audio tabs, but as yet they do nothing. This commit keeps yuzu
to the same functionality as originally branched.
* configuration: Rename files
These weren't included in the last commit. Now they are.
* configuration: setup global configuration checkbox
Global config checkbox now enables/disables the appropriate tabs in the game
properties dialog. The use global configuration setting is now saved to the
config, defaulting to true. This also addresses some changes requested in the PR.
* configuration: swap to per-game config memory for properties dialog
Does not set memory going in-game. Swaps to game values when opening the
properties dialog, then swaps back when closing it. Uses a `memcpy` to swap.
Also implements saving config files, limited to certain groups of configurations
so as to not risk setting unsafe configurations.
* configuration: change config interfaces to use config-specific pointers
When a game is booted, we need to be able to open the configuration dialogs
without changing the settings pointer in the game's emualtion. A new pointer
specific to just the configuration dialogs can be used to separate changes
to just those config dialogs without affecting the emulation.
* configuration: boot a game using per-game settings
Swaps values where needed to boot a game.
* configuration: user correct config during emulation
Creates a new pointer specifically for modifying the configuration while
emulation is in progress. Both the regular configuration dialog and the game
properties dialog now use the pointer Settings::config_values to focus edits to
the correct struct.
* settings: split Settings::values into two different structs
By splitting the settings into two mutually exclusive structs, it becomes easier,
as a developer, to determine how to use the Settings structs after per-game
configurations is merged. Other benefits include only duplicating the required
settings in memory.
* settings: move use_docked_mode to Controls group
`use_docked_mode` is set in the input settings and cannot be accessed from the
system settings. Grouping it with system settings causes it to be saved with
per-game settings, which may make transferring configs more difficult later on,
especially since docked mode cannot be set from within the game properties
dialog.
* configuration: Fix the other yuzu executables and a regression
In main.cpp, we have to get the title ID before the ROM is loaded, else the
renderer will reflect only the global settings and now the user's game specific
settings.
* settings: use a template to duplicate memory for each setting
Replaces the type of each variable in the Settings::Values struct with a new
class that allows basic data reading and writing. The new struct
Settings::Setting duplicates the data in memory and can manage global overrides
per each setting.
* configuration: correct add-ons config and swap settings when apropriate
Any add-ons interaction happens directly through the global values struct.
Swapping bewteen structs now also includes copying the necessary global configs
that cannot be changed nor saved in per-game settings. General and System config
menus now update based on whether it is viewing the global or per-game settings.
* settings: restore old values struct
No longer needed with the Settings::Setting class template.
* configuration: implement hierarchical game properties dialog
This sets the apropriate global or local data in each setting.
* clang format
* clang format take 2
can the docker container save this?
* address comments and style issues
* config: read and write settings with global awareness
Adds new functions to read and write settings while keeping the global state in
focus. Files now generated per-game are much smaller since often they only need
address the global state.
* settings: restore global state when necessary
Upon closing a game or the game properties dialog, we need to restore all global
settings to the original global state so that we can properly open the
configuration dialog or boot a different game.
* configuration: guard setting values incorrectly
This disables setting values while a game is running if the setting is
overwritten by a per game setting.
* config: don't write local settings in the global config
Simple guards to prevent writing the wrong settings in the wrong files.
* configuration: add comments, assume less, and clang format
No longer assumes that a disabled UI element means the global state is turned
off, instead opting to directly answer that question. Still however assumes a
game is running if it is in that state.
* configuration: fix a logic error
Should not be negated
* restore settings' global state regardless of accept/cancel
Fixes loading a properties dialog and causing the global config dialog to show
local settings.
* fix more logic errors
Fixed the frame limit would set the global setting from the game properties
dialog. Also strengthened the Settings::Setting member variables and simplified
the logic in config reading (ReadSettingGlobal).
* fix another logic error
In my efforts to guard RestoreGlobalState, I accidentally negated the IsPowered
condition.
* configure_audio: set toggle_stretched_audio to tristate
* fixed custom rtc and rng seed overwriting the global value
* clang format
* rebased
* clang format take 4
* address my own review
Basically revert unintended changes
* settings: literal instead of casting
"No need to cast, use 1U instead"
Thanks, Morph!
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
* Revert "settings: literal instead of casting
"
This reverts commit 95e992a87c898f3e882ffdb415bb0ef9f80f613f.
* main: fix status buttons reporting wrong settings after stop emulation
* settings: Log UseDockedMode in the Controls group
This should have happened when use_docked_mode was moved over to the controls group
internally. This just reflects this in the log.
* main: load settings if the file has a title id
In other words, don't exit if the loader has trouble getting a title id.
* use a zero
* settings: initalize resolution factor with constructor instead of casting
* Revert "settings: initalize resolution factor with constructor instead of casting"
This reverts commit 54c35ecb46a29953842614620f9b7de1aa9d5dc8.
* configure_graphics: guard device selector when Vulkan is global
Prevents the user from editing the device selector if Vulkan is the global
renderer backend. Also resets the vulkan_device variable when the users
switches back-and-forth between global and Vulkan.
* address reviewer concerns
Changes function variables to const wherever they don't need to be changed. Sets Settings::Setting to final as it should not be inherited from. Sets ConfigurationShared::use_global_text to static.
Co-Authored-By: VolcaEM <volcaem@users.noreply.github.com>
* main: load per-game settings after LoadROM
This prevents `Restart Emulation` from restoring the global settings *after* the per-game settings were applied. Thanks to BSoDGamingYT for finding this bug.
* Revert "main: load per-game settings after LoadROM"
This reverts commit 9d0d48c52d2dcf3bfb1806cc8fa7d5a271a8a804.
* main: only restore global settings when necessary
Loading the per-game settings cannot happen after the ROM is loaded, so we have to specify when to restore the global state. Again thanks to BSoD for finding the bug.
* configuration_shared: address reviewer concerns except operator overrides
Dropping operator override usage in next commit.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
* settings: Drop operator overrides from Setting template
Requires using GetValue and SetValue explicitly. Also reverts a change that broke title ID formatting in the game properties dialog.
* complete rebase
* configuration_shared: translate "Use global configuration"
Uses ConfigurePerGame to do so, since its usage, at least as of now, corresponds with ConfigurationShared.
* configure_per_game: address reviewer concern
As far as I understand, it prevents the program from unnecessarily copying strings.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
Co-authored-by: VolcaEM <volcaem@users.noreply.github.com>
Co-authored-by: LC <lioncash@users.noreply.github.com>
2020-07-09 22:42:09 -04:00
|
|
|
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
|
2018-09-18 11:10:16 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-28 22:46:51 -04:00
|
|
|
void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
|
|
|
|
|
|
|
|
const auto& sm = system.ServiceManager();
|
|
|
|
const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
|
|
|
|
ASSERT(apm_sys != nullptr);
|
|
|
|
|
|
|
|
apm_sys->SetCpuBoostMode(ctx);
|
|
|
|
}
|
|
|
|
|
2021-04-23 22:46:25 -04:00
|
|
|
void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
|
|
|
|
Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-01-26 13:18:13 -05:00
|
|
|
IStorageImpl::~IStorageImpl() = default;
|
|
|
|
|
|
|
|
class StorageDataImpl final : public IStorageImpl {
|
|
|
|
public:
|
2021-05-16 01:46:30 -04:00
|
|
|
explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {}
|
2020-01-26 13:18:13 -05:00
|
|
|
|
|
|
|
std::vector<u8>& GetData() override {
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<u8>& GetData() const override {
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t GetSize() const override {
|
|
|
|
return buffer.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<u8> buffer;
|
|
|
|
};
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer)
|
|
|
|
: ServiceFramework{system_, "IStorage"}, impl{std::make_shared<StorageDataImpl>(
|
|
|
|
std::move(buffer))} {
|
2020-01-26 13:18:13 -05:00
|
|
|
Register();
|
|
|
|
}
|
|
|
|
|
|
|
|
void IStorage::Register() {
|
2018-11-09 20:04:43 -05:00
|
|
|
// clang-format off
|
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, &IStorage::Open, "Open"},
|
|
|
|
{1, nullptr, "OpenTransferStorage"},
|
|
|
|
};
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
2018-11-11 16:39:25 -05:00
|
|
|
IStorage::~IStorage() = default;
|
|
|
|
|
2020-01-26 13:18:13 -05:00
|
|
|
void IStorage::Open(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
|
|
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-11-26 15:19:08 -05:00
|
|
|
rb.PushIpcInterface<IStorageAccessor>(system, *this);
|
2018-11-09 20:04:43 -05:00
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
|
2020-09-28 10:00:15 -04:00
|
|
|
const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-03-26 22:59:18 -04:00
|
|
|
rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
|
2019-06-28 22:46:51 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-06-28 22:46:51 -04:00
|
|
|
rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2018-11-09 20:06:50 -05:00
|
|
|
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
|
2018-02-02 16:03:40 -05:00
|
|
|
public:
|
2020-11-26 15:19:08 -05:00
|
|
|
explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<Applets::Applet> applet_)
|
|
|
|
: ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-02-02 16:03:40 -05:00
|
|
|
static const FunctionInfo functions[] = {
|
2018-11-09 20:06:50 -05:00
|
|
|
{0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
|
2018-11-11 16:57:59 -05:00
|
|
|
{1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
|
2018-11-09 20:06:50 -05:00
|
|
|
{10, &ILibraryAppletAccessor::Start, "Start"},
|
|
|
|
{20, nullptr, "RequestExit"},
|
|
|
|
{25, nullptr, "Terminate"},
|
|
|
|
{30, &ILibraryAppletAccessor::GetResult, "GetResult"},
|
|
|
|
{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
|
2021-01-20 23:35:12 -05:00
|
|
|
{60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
|
2018-11-09 20:06:50 -05:00
|
|
|
{100, &ILibraryAppletAccessor::PushInData, "PushInData"},
|
|
|
|
{101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
|
|
|
|
{102, nullptr, "PushExtraStorage"},
|
|
|
|
{103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
|
|
|
|
{104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
|
2018-11-11 16:41:31 -05:00
|
|
|
{105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
|
2018-11-09 20:06:50 -05:00
|
|
|
{106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
|
|
|
|
{110, nullptr, "NeedsToExitProcess"},
|
|
|
|
{120, nullptr, "GetLibraryAppletInfo"},
|
|
|
|
{150, nullptr, "RequestForAppletToGetForeground"},
|
2020-06-28 02:51:28 -04:00
|
|
|
{160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
|
2018-02-02 16:03:40 -05:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-11-09 20:06:50 -05:00
|
|
|
void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-09 20:06:50 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-10 05:34:26 -04:00
|
|
|
rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent());
|
2018-11-09 20:06:50 -05:00
|
|
|
}
|
|
|
|
|
2018-11-11 16:57:59 -05:00
|
|
|
void IsCompleted(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-11 16:57:59 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
2018-02-02 16:03:40 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-11-11 16:57:59 -05:00
|
|
|
rb.Push<u32>(applet->TransactionComplete());
|
|
|
|
}
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2018-11-11 16:57:59 -05:00
|
|
|
void GetResult(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-11 16:57:59 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(applet->GetStatus());
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2021-01-20 23:35:12 -05:00
|
|
|
void PresetLibraryAppletGpuTimeSliceZero(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-11-09 20:08:25 -05:00
|
|
|
void Start(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-09 20:08:25 -05:00
|
|
|
ASSERT(applet != nullptr);
|
2018-06-03 14:21:45 -04:00
|
|
|
|
2018-11-20 12:02:16 -05:00
|
|
|
applet->Initialize();
|
2018-11-19 14:24:36 -05:00
|
|
|
applet->Execute();
|
2018-11-11 16:41:31 -05:00
|
|
|
|
2018-11-09 20:08:25 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
2018-06-03 14:21:45 -04:00
|
|
|
|
2018-11-09 20:06:50 -05:00
|
|
|
void PushInData(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-09 20:06:50 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
2020-02-02 00:38:22 -05:00
|
|
|
applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>());
|
2018-06-03 14:21:45 -04:00
|
|
|
|
2018-09-19 01:09:59 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2018-06-03 14:21:45 -04:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-11-09 20:06:50 -05:00
|
|
|
void PopOutData(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2020-04-17 19:22:43 -04:00
|
|
|
auto storage = applet->GetBroker().PopNormalDataToGame();
|
2018-11-19 14:24:36 -05:00
|
|
|
if (storage == nullptr) {
|
2021-03-11 22:31:05 -05:00
|
|
|
LOG_DEBUG(Service_AM,
|
2018-11-26 20:29:06 -05:00
|
|
|
"storage is a nullptr. There is no data in the current normal channel");
|
2020-01-29 22:25:57 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2018-11-19 14:24:36 -05:00
|
|
|
rb.Push(ERR_NO_DATA_IN_CHANNEL);
|
2018-11-17 12:19:06 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-29 22:25:57 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
2018-11-09 20:06:50 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-02-02 00:38:22 -05:00
|
|
|
rb.PushIpcInterface<IStorage>(std::move(storage));
|
2018-11-09 20:06:50 -05:00
|
|
|
}
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2018-11-09 20:07:42 -05:00
|
|
|
void PushInteractiveInData(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-09 20:07:42 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
2020-02-02 00:38:22 -05:00
|
|
|
applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>());
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2018-11-11 16:41:31 -05:00
|
|
|
ASSERT(applet->IsInitialized());
|
2018-11-19 14:24:36 -05:00
|
|
|
applet->ExecuteInteractive();
|
|
|
|
applet->Execute();
|
2018-11-11 16:41:31 -05:00
|
|
|
|
2018-09-19 01:09:59 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2018-02-02 16:03:40 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-11-09 20:07:42 -05:00
|
|
|
void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2020-04-17 19:22:43 -04:00
|
|
|
auto storage = applet->GetBroker().PopInteractiveDataToGame();
|
2018-11-19 14:24:36 -05:00
|
|
|
if (storage == nullptr) {
|
2021-03-11 22:31:05 -05:00
|
|
|
LOG_DEBUG(Service_AM,
|
2018-11-26 20:29:06 -05:00
|
|
|
"storage is a nullptr. There is no data in the current interactive channel");
|
2020-01-29 22:25:57 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2018-11-19 14:24:36 -05:00
|
|
|
rb.Push(ERR_NO_DATA_IN_CHANNEL);
|
2018-11-17 12:19:06 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-29 22:25:57 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
2018-11-09 20:07:42 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-02-02 00:38:22 -05:00
|
|
|
rb.PushIpcInterface<IStorage>(std::move(storage));
|
2018-11-09 20:07:42 -05:00
|
|
|
}
|
|
|
|
|
2018-11-11 16:41:31 -05:00
|
|
|
void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-11 16:41:31 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-11-20 12:02:16 -05:00
|
|
|
rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
|
2018-11-11 16:41:31 -05:00
|
|
|
}
|
2018-11-09 20:07:42 -05:00
|
|
|
|
2018-11-11 16:41:31 -05:00
|
|
|
void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-09 20:07:42 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2018-11-20 12:02:16 -05:00
|
|
|
rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2020-06-28 02:51:28 -04:00
|
|
|
void GetIndirectLayerConsumerHandle(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
// We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
|
|
|
|
// actually used anywhere
|
|
|
|
constexpr u64 handle = 0xdeadbeef;
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push(handle);
|
|
|
|
}
|
|
|
|
|
2018-11-09 20:06:50 -05:00
|
|
|
std::shared_ptr<Applets::Applet> applet;
|
|
|
|
};
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_)
|
|
|
|
: ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} {
|
2018-11-09 20:04:07 -05:00
|
|
|
// clang-format off
|
2018-06-03 14:23:44 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
2018-11-09 20:04:07 -05:00
|
|
|
{0, &IStorageAccessor::GetSize, "GetSize"},
|
|
|
|
{10, &IStorageAccessor::Write, "Write"},
|
|
|
|
{11, &IStorageAccessor::Read, "Read"},
|
2018-06-03 14:23:44 -04:00
|
|
|
};
|
2018-11-09 20:04:07 -05:00
|
|
|
// clang-format on
|
2018-10-21 16:40:17 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-11-11 16:39:25 -05:00
|
|
|
IStorageAccessor::~IStorageAccessor() = default;
|
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-01-26 13:18:13 -05:00
|
|
|
rb.Push(static_cast<u64>(backing.GetSize()));
|
2018-11-09 20:04:07 -05:00
|
|
|
}
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
const u64 offset{rp.Pop<u64>()};
|
|
|
|
const std::vector<u8> data{ctx.ReadBuffer()};
|
2021-02-13 05:30:33 -05:00
|
|
|
const std::size_t size{std::min(data.size(), backing.GetSize() - offset)};
|
2018-06-03 23:37:17 -04:00
|
|
|
|
2021-02-13 05:30:33 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
|
2018-12-24 16:16:28 -05:00
|
|
|
|
2021-02-13 05:30:33 -05:00
|
|
|
if (offset > backing.GetSize()) {
|
2018-11-26 04:05:09 -05:00
|
|
|
LOG_ERROR(Service_AM,
|
|
|
|
"offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
|
2021-02-13 05:30:33 -05:00
|
|
|
backing.GetSize(), size, offset);
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-11-19 14:24:36 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
|
2019-05-18 18:49:19 -04:00
|
|
|
return;
|
2018-11-19 14:24:36 -05:00
|
|
|
}
|
2018-06-03 23:37:17 -04:00
|
|
|
|
2021-02-13 05:30:33 -05:00
|
|
|
std::memcpy(backing.GetData().data() + offset, data.data(), size);
|
2018-06-03 23:37:17 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
const u64 offset{rp.Pop<u64>()};
|
2021-02-13 05:30:33 -05:00
|
|
|
const std::size_t size{std::min(ctx.GetWriteBufferSize(), backing.GetSize() - offset)};
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2018-12-24 16:16:28 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
|
|
|
|
|
2021-02-13 05:30:33 -05:00
|
|
|
if (offset > backing.GetSize()) {
|
2018-11-26 04:05:09 -05:00
|
|
|
LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
|
2020-01-26 13:18:13 -05:00
|
|
|
backing.GetSize(), size, offset);
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-11-19 14:24:36 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
|
2019-05-18 18:49:19 -04:00
|
|
|
return;
|
2018-11-19 14:24:36 -05:00
|
|
|
}
|
2018-06-03 23:43:31 -04:00
|
|
|
|
2020-01-26 13:18:13 -05:00
|
|
|
ctx.WriteBuffer(backing.GetData().data() + offset, size);
|
2018-06-03 23:43:31 -04:00
|
|
|
|
2018-11-09 20:04:07 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
2018-06-03 14:23:44 -04:00
|
|
|
|
2019-07-11 00:53:55 -04:00
|
|
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
|
2020-11-26 15:19:08 -05:00
|
|
|
: ServiceFramework{system_, "ILibraryAppletCreator"} {
|
2018-06-03 14:19:24 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
|
|
|
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
|
|
|
{2, nullptr, "AreAnyLibraryAppletsLeft"},
|
|
|
|
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
|
2018-11-09 20:04:07 -05:00
|
|
|
{11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
|
2021-03-12 10:14:01 -05:00
|
|
|
{12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
|
2018-06-03 14:19:24 -04:00
|
|
|
};
|
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
|
|
|
|
|
2018-06-03 14:19:24 -04:00
|
|
|
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
|
2018-11-09 20:14:01 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
2021-03-12 10:14:01 -05:00
|
|
|
|
2019-03-11 19:33:18 -04:00
|
|
|
const auto applet_id = rp.PopRaw<Applets::AppletId>();
|
2021-02-06 02:31:13 -05:00
|
|
|
const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
|
2018-11-09 20:14:01 -05:00
|
|
|
|
2020-12-07 22:00:34 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
|
|
|
applet_mode);
|
2018-11-09 20:14:01 -05:00
|
|
|
|
2019-07-11 00:53:55 -04:00
|
|
|
const auto& applet_manager{system.GetAppletManager()};
|
2021-02-06 02:31:13 -05:00
|
|
|
const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
|
2018-11-09 20:14:01 -05:00
|
|
|
|
|
|
|
if (applet == nullptr) {
|
2020-12-07 22:00:34 -05:00
|
|
|
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-11-09 20:14:01 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2019-11-12 05:38:12 -05:00
|
|
|
rb.Push(RESULT_UNKNOWN);
|
2018-11-09 20:14:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-03 14:19:24 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
|
|
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-11-26 15:19:08 -05:00
|
|
|
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
|
2018-06-03 14:19:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
2021-03-12 10:14:01 -05:00
|
|
|
|
|
|
|
const s64 size{rp.Pop<s64>()};
|
|
|
|
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called, size={}", size);
|
|
|
|
|
2021-03-12 10:14:01 -05:00
|
|
|
if (size <= 0) {
|
|
|
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-03 14:19:24 -04:00
|
|
|
std::vector<u8> buffer(size);
|
|
|
|
|
2018-09-19 01:09:59 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
2018-06-03 14:19:24 -04:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-11-26 15:19:08 -05:00
|
|
|
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
|
2018-06-03 14:19:24 -04:00
|
|
|
}
|
|
|
|
|
2018-11-09 20:01:20 -05:00
|
|
|
void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
|
2021-03-12 10:14:01 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
|
|
|
|
struct Parameters {
|
|
|
|
u8 permissions;
|
|
|
|
s64 size;
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto parameters{rp.PopRaw<Parameters>()};
|
|
|
|
const auto handle{ctx.GetCopyHandle(0)};
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2021-03-12 10:14:01 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
|
|
|
|
parameters.size, handle);
|
|
|
|
|
|
|
|
if (parameters.size <= 0) {
|
|
|
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto transfer_mem =
|
2021-04-04 03:56:09 -04:00
|
|
|
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
|
2021-03-12 10:14:01 -05:00
|
|
|
|
2021-04-04 03:56:09 -04:00
|
|
|
if (transfer_mem.IsNull()) {
|
2021-03-12 10:14:01 -05:00
|
|
|
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-04 03:56:09 -04:00
|
|
|
const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress());
|
2021-03-12 10:14:01 -05:00
|
|
|
const u8* const mem_end = mem_begin + transfer_mem->GetSize();
|
|
|
|
std::vector<u8> memory{mem_begin, mem_end};
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.PushIpcInterface<IStorage>(system, std::move(memory));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) {
|
2018-11-09 20:01:20 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
|
2021-03-12 10:14:01 -05:00
|
|
|
const s64 size{rp.Pop<s64>()};
|
|
|
|
const auto handle{ctx.GetCopyHandle(0)};
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
|
|
|
|
|
|
|
|
if (size <= 0) {
|
|
|
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
2018-11-09 20:01:20 -05:00
|
|
|
|
2020-01-26 13:18:13 -05:00
|
|
|
auto transfer_mem =
|
2021-04-17 03:52:53 -04:00
|
|
|
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
|
2018-11-09 20:01:20 -05:00
|
|
|
|
2021-04-17 03:52:53 -04:00
|
|
|
if (transfer_mem.IsNull()) {
|
2021-03-12 10:14:01 -05:00
|
|
|
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
|
2018-11-09 20:01:20 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
2019-11-12 05:38:12 -05:00
|
|
|
rb.Push(RESULT_UNKNOWN);
|
2018-11-09 20:01:20 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-17 03:52:53 -04:00
|
|
|
const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress());
|
2019-04-03 16:35:14 -04:00
|
|
|
const u8* const mem_end = mem_begin + transfer_mem->GetSize();
|
2018-11-11 16:39:25 -05:00
|
|
|
std::vector<u8> memory{mem_begin, mem_end};
|
2018-11-09 20:01:20 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-11-26 15:19:08 -05:00
|
|
|
rb.PushIpcInterface<IStorage>(system, std::move(memory));
|
2018-11-09 20:01:20 -05:00
|
|
|
}
|
|
|
|
|
2019-07-11 00:53:55 -04:00
|
|
|
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
2021-04-04 03:56:09 -04:00
|
|
|
: ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()},
|
|
|
|
friend_invitation_storage_channel_event{system.Kernel()},
|
|
|
|
health_warning_disappeared_system_event{system.Kernel()} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-02-02 16:03:40 -05:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
|
|
|
|
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
|
|
|
|
{12, nullptr, "CreateApplicationAndRequestToStart"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
|
|
|
|
{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
|
2018-02-05 20:58:11 -05:00
|
|
|
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
|
|
|
|
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
|
2018-05-26 00:21:03 -04:00
|
|
|
{23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{24, nullptr, "GetLaunchStorageInfoForDebug"},
|
2018-12-10 22:17:45 -05:00
|
|
|
{25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
|
|
|
|
{26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{27, nullptr, "CreateCacheStorage"},
|
2021-04-07 01:59:35 -04:00
|
|
|
{28, nullptr, "GetSaveDataSizeMax"},
|
|
|
|
{29, nullptr, "GetCacheStorageMax"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
|
|
|
|
{31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
|
2018-10-19 09:01:10 -04:00
|
|
|
{32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
|
|
|
|
{33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{34, nullptr, "SelectApplicationLicense"},
|
2021-04-07 01:59:35 -04:00
|
|
|
{35, nullptr, "GetDeviceSaveDataSizeMax"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
|
2018-06-05 18:44:01 -04:00
|
|
|
{50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{60, nullptr, "SetMediaPlaybackStateForApplication"},
|
2021-01-31 03:11:03 -05:00
|
|
|
{65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
|
2018-02-02 16:03:40 -05:00
|
|
|
{66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
|
|
|
|
{67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
|
|
|
|
{70, nullptr, "RequestToShutdown"},
|
|
|
|
{71, nullptr, "RequestToReboot"},
|
2020-04-20 15:18:23 -04:00
|
|
|
{72, nullptr, "RequestToSleep"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
|
2018-11-17 09:05:55 -05:00
|
|
|
{90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
|
2019-11-02 20:26:13 -04:00
|
|
|
{100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
|
|
|
|
{101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
|
|
|
|
{102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
|
2019-11-14 15:59:50 -05:00
|
|
|
{110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
|
2019-11-11 10:21:45 -05:00
|
|
|
{111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
|
2020-11-24 18:17:43 -05:00
|
|
|
{120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
|
|
|
|
{121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
|
|
|
|
{122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
|
2020-09-17 20:45:51 -04:00
|
|
|
{123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
|
2020-06-26 20:32:26 -04:00
|
|
|
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
|
2019-09-04 11:43:04 -04:00
|
|
|
{130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
|
2021-04-07 01:59:35 -04:00
|
|
|
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
|
2020-04-30 08:37:26 -04:00
|
|
|
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
|
2021-01-30 21:43:55 -05:00
|
|
|
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{150, nullptr, "GetNotificationStorageChannelEvent"},
|
|
|
|
{151, nullptr, "TryPopFromNotificationStorageChannel"},
|
2021-02-02 10:47:09 -05:00
|
|
|
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{170, nullptr, "SetHdcpAuthenticationActivated"},
|
2020-10-27 21:19:44 -04:00
|
|
|
{180, nullptr, "GetLaunchRequiredVersion"},
|
|
|
|
{181, nullptr, "UpgradeLaunchRequiredVersion"},
|
2021-04-07 01:59:35 -04:00
|
|
|
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
|
|
|
|
{200, nullptr, "GetLastApplicationExitReason"},
|
2018-04-10 11:36:00 -04:00
|
|
|
{500, nullptr, "StartContinuousRecordingFlushForDebug"},
|
|
|
|
{1000, nullptr, "CreateMovieMaker"},
|
|
|
|
{1001, nullptr, "PrepareForJit"},
|
2018-02-02 16:03:40 -05:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
RegisterHandlers(functions);
|
2019-09-04 11:43:04 -04:00
|
|
|
|
2021-04-09 19:56:11 -04:00
|
|
|
Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event));
|
|
|
|
Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event));
|
|
|
|
Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event));
|
|
|
|
|
2021-04-04 03:56:09 -04:00
|
|
|
gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent");
|
|
|
|
friend_invitation_storage_channel_event.Initialize(
|
|
|
|
"IApplicationFunctions:FriendInvitationStorageChannelEvent");
|
|
|
|
health_warning_disappeared_system_event.Initialize(
|
|
|
|
"IApplicationFunctions:HealthWarningDisappearedSystemEvent");
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IApplicationFunctions::~IApplicationFunctions() = default;
|
|
|
|
|
2018-11-17 09:05:55 -05:00
|
|
|
void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-11-17 09:05:55 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-11-02 20:26:13 -04:00
|
|
|
void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
|
|
|
|
Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx) {
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const auto is_visible = rp.Pop<bool>();
|
|
|
|
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-10-19 09:01:10 -04:00
|
|
|
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
|
|
|
|
Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-10-19 09:01:10 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(
|
|
|
|
Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-10-19 09:01:10 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::BeginBlockingHomeButton(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-10-19 09:01:10 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::EndBlockingHomeButton(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-10-19 09:01:10 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
|
2019-05-01 22:40:51 -04:00
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
const auto kind = rp.PopEnum<LaunchParameterKind>();
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2020-12-07 22:00:34 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called, kind={:08X}", kind);
|
2018-10-09 21:49:29 -04:00
|
|
|
|
2019-05-01 22:40:51 -04:00
|
|
|
if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) {
|
2019-10-12 09:23:40 -04:00
|
|
|
const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) {
|
|
|
|
return system.GetFileSystemController().GetBCATDirectory(tid);
|
|
|
|
});
|
2019-10-06 13:02:23 -04:00
|
|
|
const auto build_id_full = system.GetCurrentProcessBuildID();
|
2019-05-01 22:40:51 -04:00
|
|
|
u64 build_id{};
|
|
|
|
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
|
2018-10-10 21:49:20 -04:00
|
|
|
|
2020-01-26 13:18:13 -05:00
|
|
|
auto data = backend->GetLaunchParameter({system.CurrentProcess()->GetTitleID(), build_id});
|
2019-05-01 22:40:51 -04:00
|
|
|
if (data.has_value()) {
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-11-26 15:19:08 -05:00
|
|
|
rb.PushIpcInterface<IStorage>(system, std::move(*data));
|
2019-05-01 22:40:51 -04:00
|
|
|
launch_popped_application_specific = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (kind == LaunchParameterKind::AccountPreselectedUser &&
|
|
|
|
!launch_popped_account_preselect) {
|
|
|
|
LaunchParameterAccountPreselectedUser params{};
|
2018-02-02 16:03:40 -05:00
|
|
|
|
2019-05-01 22:40:51 -04:00
|
|
|
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
|
|
|
|
params.is_account_selected = 1;
|
2018-10-13 13:02:33 -04:00
|
|
|
|
2019-05-01 22:40:51 -04:00
|
|
|
Account::ProfileManager profile_manager{};
|
2020-10-20 22:07:39 -04:00
|
|
|
const auto uuid = profile_manager.GetUser(Settings::values.current_user);
|
2019-05-01 22:40:51 -04:00
|
|
|
ASSERT(uuid);
|
|
|
|
params.current_user = uuid->uuid;
|
2018-10-13 13:02:33 -04:00
|
|
|
|
2019-05-01 22:40:51 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
|
|
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
|
|
|
std::memcpy(buffer.data(), ¶ms, buffer.size());
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
|
2019-05-01 22:40:51 -04:00
|
|
|
launch_popped_account_preselect = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(ERR_NO_DATA_IN_CHANNEL);
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(
|
|
|
|
Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-02-05 20:58:11 -05:00
|
|
|
void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
|
2018-03-04 13:03:58 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
2019-04-17 11:59:07 -04:00
|
|
|
u128 user_id = rp.PopRaw<u128>();
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
|
|
|
|
|
2020-07-30 15:29:39 -04:00
|
|
|
FileSys::SaveDataAttribute attribute{};
|
|
|
|
attribute.title_id = system.CurrentProcess()->GetTitleID();
|
|
|
|
attribute.user_id = user_id;
|
|
|
|
attribute.type = FileSys::SaveDataType::SaveData;
|
2019-09-21 18:43:11 -04:00
|
|
|
const auto res = system.GetFileSystemController().CreateSaveData(
|
2020-07-30 15:29:39 -04:00
|
|
|
FileSys::SaveDataSpaceId::NandUser, attribute);
|
2018-03-04 13:03:58 -05:00
|
|
|
|
2018-02-18 18:09:52 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
2019-04-17 11:59:07 -04:00
|
|
|
rb.Push(res.Code());
|
2018-02-18 18:09:52 -05:00
|
|
|
rb.Push<u64>(0);
|
2019-04-17 11:59:07 -04:00
|
|
|
}
|
2018-02-05 20:58:11 -05:00
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
|
|
|
|
// Takes an input u32 Result, no output.
|
2018-11-17 09:05:55 -05:00
|
|
|
// For example, in some cases official apps use this with error 0x2A2 then
|
|
|
|
// uses svcBreak.
|
2018-02-02 16:03:40 -05:00
|
|
|
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
u32 result = rp.Pop<u32>();
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
|
2018-02-02 16:03:40 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-05-26 00:21:03 -04:00
|
|
|
void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
|
2020-04-29 08:13:56 -04:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
std::array<u8, 0x10> version_string{};
|
|
|
|
|
2020-07-04 18:49:41 -04:00
|
|
|
const auto res = [this] {
|
|
|
|
const auto title_id = system.CurrentProcess()->GetTitleID();
|
|
|
|
|
2020-11-18 07:53:10 -05:00
|
|
|
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
|
|
|
system.GetContentProvider()};
|
2021-05-16 01:46:30 -04:00
|
|
|
auto metadata = pm.GetControlMetadata();
|
|
|
|
if (metadata.first != nullptr) {
|
|
|
|
return metadata;
|
2020-07-04 18:49:41 -04:00
|
|
|
}
|
|
|
|
|
2020-11-18 07:53:10 -05:00
|
|
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
|
|
|
|
system.GetFileSystemController(),
|
|
|
|
system.GetContentProvider()};
|
2020-07-04 18:49:41 -04:00
|
|
|
return pm_update.GetControlMetadata();
|
|
|
|
}();
|
|
|
|
|
2020-04-29 08:13:56 -04:00
|
|
|
if (res.first != nullptr) {
|
|
|
|
const auto& version = res.first->GetVersionString();
|
|
|
|
std::copy(version.begin(), version.end(), version_string.begin());
|
|
|
|
} else {
|
2020-07-04 18:49:41 -04:00
|
|
|
constexpr char default_version[]{"1.0.0"};
|
|
|
|
std::memcpy(version_string.data(), default_version, sizeof(default_version));
|
2020-04-29 08:13:56 -04:00
|
|
|
}
|
2018-11-26 01:06:13 -05:00
|
|
|
|
2018-05-26 00:21:03 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 6};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2020-04-29 08:13:56 -04:00
|
|
|
rb.PushRaw(version_string);
|
2018-05-26 00:21:03 -04:00
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
|
2018-04-28 20:30:53 -04:00
|
|
|
// TODO(bunnei): This should be configurable
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
2019-05-23 03:55:56 -04:00
|
|
|
// Get supported languages from NACP, if possible
|
|
|
|
// Default to 0 (all languages supported)
|
|
|
|
u32 supported_languages = 0;
|
|
|
|
|
2020-07-08 12:45:06 -04:00
|
|
|
const auto res = [this] {
|
|
|
|
const auto title_id = system.CurrentProcess()->GetTitleID();
|
|
|
|
|
2020-11-18 07:53:10 -05:00
|
|
|
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
|
|
|
system.GetContentProvider()};
|
2021-05-16 01:46:30 -04:00
|
|
|
auto metadata = pm.GetControlMetadata();
|
|
|
|
if (metadata.first != nullptr) {
|
|
|
|
return metadata;
|
2020-07-08 12:45:06 -04:00
|
|
|
}
|
|
|
|
|
2020-11-18 07:53:10 -05:00
|
|
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
|
|
|
|
system.GetFileSystemController(),
|
|
|
|
system.GetContentProvider()};
|
2020-07-08 12:45:06 -04:00
|
|
|
return pm_update.GetControlMetadata();
|
|
|
|
}();
|
|
|
|
|
2019-05-23 03:55:56 -04:00
|
|
|
if (res.first != nullptr) {
|
|
|
|
supported_languages = res.first->GetSupportedLanguages();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call IApplicationManagerInterface implementation.
|
2019-07-11 00:53:55 -04:00
|
|
|
auto& service_manager = system.ServiceManager();
|
|
|
|
auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
|
2019-05-23 03:55:56 -04:00
|
|
|
auto app_man = ns_am2->GetApplicationManagerInterface();
|
|
|
|
|
|
|
|
// Get desired application language
|
|
|
|
const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages);
|
|
|
|
if (res_lang.Failed()) {
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(res_lang.Code());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert to settings language code.
|
|
|
|
const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang);
|
|
|
|
if (res_code.Failed()) {
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(res_code.Code());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code);
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-05-23 03:55:56 -04:00
|
|
|
rb.Push(*res_code);
|
2018-02-02 16:03:40 -05:00
|
|
|
}
|
|
|
|
|
2021-01-31 03:11:03 -05:00
|
|
|
void IApplicationFunctions::IsGamePlayRecordingSupported(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
constexpr bool gameplay_recording_supported = false;
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push(gameplay_recording_supported);
|
|
|
|
}
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-02-02 16:03:40 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
|
|
|
|
}
|
|
|
|
|
2018-06-05 18:44:01 -04:00
|
|
|
void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-06-05 18:44:01 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 6};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
// Returns a 128-bit UUID
|
|
|
|
rb.Push<u64>(0);
|
|
|
|
rb.Push<u64>(0);
|
|
|
|
}
|
|
|
|
|
2018-12-10 22:17:45 -05:00
|
|
|
void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
|
2019-11-14 16:29:31 -05:00
|
|
|
struct Parameters {
|
|
|
|
FileSys::SaveDataType type;
|
|
|
|
u128 user_id;
|
|
|
|
u64 new_normal_size;
|
|
|
|
u64 new_journal_size;
|
|
|
|
};
|
|
|
|
static_assert(sizeof(Parameters) == 40);
|
|
|
|
|
2018-12-10 22:17:45 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
2019-11-14 16:29:31 -05:00
|
|
|
const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
|
2018-12-10 22:17:45 -05:00
|
|
|
|
|
|
|
LOG_DEBUG(Service_AM,
|
|
|
|
"called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
|
|
|
|
"new_journal={:016X}",
|
|
|
|
static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
|
|
|
|
|
2019-09-21 18:43:11 -04:00
|
|
|
system.GetFileSystemController().WriteSaveDataSize(
|
|
|
|
type, system.CurrentProcess()->GetTitleID(), user_id, {new_normal_size, new_journal_size});
|
2018-12-10 22:17:45 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
// The following value is used upon failure to help the system recover.
|
|
|
|
// Since we always succeed, this should be 0.
|
|
|
|
rb.Push<u64>(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
|
2019-11-14 16:29:31 -05:00
|
|
|
struct Parameters {
|
|
|
|
FileSys::SaveDataType type;
|
|
|
|
u128 user_id;
|
|
|
|
};
|
|
|
|
static_assert(sizeof(Parameters) == 24);
|
|
|
|
|
2018-12-10 22:17:45 -05:00
|
|
|
IPC::RequestParser rp{ctx};
|
2019-11-14 16:29:31 -05:00
|
|
|
const auto [type, user_id] = rp.PopRaw<Parameters>();
|
2018-12-10 22:17:45 -05:00
|
|
|
|
2020-12-07 22:00:34 -05:00
|
|
|
LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
|
|
|
|
user_id[0]);
|
2018-12-10 22:17:45 -05:00
|
|
|
|
2019-09-21 18:43:11 -04:00
|
|
|
const auto size = system.GetFileSystemController().ReadSaveDataSize(
|
2019-04-22 17:53:58 -04:00
|
|
|
type, system.CurrentProcess()->GetTitleID(), user_id);
|
2018-12-10 22:17:45 -05:00
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 6};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push(size.normal);
|
|
|
|
rb.Push(size.journal);
|
|
|
|
}
|
|
|
|
|
2019-11-14 15:59:50 -05:00
|
|
|
void IApplicationFunctions::QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx) {
|
2019-09-04 11:43:04 -04:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2019-11-14 15:59:50 -05:00
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
2019-09-04 11:43:04 -04:00
|
|
|
rb.Push(RESULT_SUCCESS);
|
2019-11-14 15:59:50 -05:00
|
|
|
rb.Push<u32>(0);
|
2019-09-04 11:43:04 -04:00
|
|
|
}
|
|
|
|
|
2019-11-11 10:21:45 -05:00
|
|
|
void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<u32>(0);
|
|
|
|
}
|
|
|
|
|
2020-11-24 18:17:43 -05:00
|
|
|
void IApplicationFunctions::ExecuteProgram(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
|
|
[[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
|
|
|
|
[[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
|
|
|
|
const auto program_index = rp.Pop<u64>();
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
|
|
|
|
system.ExecuteProgram(program_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::ClearUserChannel(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IApplicationFunctions::UnpopToUserChannel(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-09-17 20:45:51 -04:00
|
|
|
void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
rb.Push<s32>(previous_program_index);
|
|
|
|
}
|
|
|
|
|
2019-11-14 15:59:50 -05:00
|
|
|
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-04 03:56:09 -04:00
|
|
|
rb.PushCopyObjects(gpu_error_detected_event.GetReadableEvent());
|
2019-11-14 15:59:50 -05:00
|
|
|
}
|
|
|
|
|
2020-04-30 08:37:26 -04:00
|
|
|
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-04 03:56:09 -04:00
|
|
|
rb.PushCopyObjects(friend_invitation_storage_channel_event.GetReadableEvent());
|
2020-04-30 08:37:26 -04:00
|
|
|
}
|
|
|
|
|
2021-01-30 21:43:55 -05:00
|
|
|
void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
|
|
|
|
Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(ERR_NO_DATA_IN_CHANNEL);
|
|
|
|
}
|
|
|
|
|
2021-02-02 10:47:09 -05:00
|
|
|
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-04 03:56:09 -04:00
|
|
|
rb.PushCopyObjects(health_warning_disappeared_system_event.GetReadableEvent());
|
2021-02-02 10:47:09 -05:00
|
|
|
}
|
|
|
|
|
2020-11-24 17:31:58 -05:00
|
|
|
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
|
|
|
|
Core::System& system) {
|
2019-07-11 00:53:55 -04:00
|
|
|
auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
|
|
|
|
// Needed on game boot
|
|
|
|
message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
2018-11-07 02:01:33 -05:00
|
|
|
|
2019-06-06 19:46:36 -04:00
|
|
|
std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
|
|
|
|
std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
|
2020-11-26 15:19:08 -05:00
|
|
|
std::make_shared<IdleSys>(system)->InstallAsService(service_manager);
|
|
|
|
std::make_shared<OMM>(system)->InstallAsService(service_manager);
|
|
|
|
std::make_shared<SPSM>(system)->InstallAsService(service_manager);
|
|
|
|
std::make_shared<TCAP>(system)->InstallAsService(service_manager);
|
2017-10-14 22:50:04 -04:00
|
|
|
}
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
|
2021-04-04 03:56:09 -04:00
|
|
|
: ServiceFramework{system_, "IHomeMenuFunctions"}, pop_from_general_channel_event{
|
|
|
|
system.Kernel()} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-05-07 11:27:30 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
|
|
|
|
{11, nullptr, "LockForeground"},
|
|
|
|
{12, nullptr, "UnlockForeground"},
|
|
|
|
{20, nullptr, "PopFromGeneralChannel"},
|
2020-04-30 21:20:43 -04:00
|
|
|
{21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
|
2018-05-07 11:27:30 -04:00
|
|
|
{30, nullptr, "GetHomeButtonWriterLockAccessor"},
|
|
|
|
{31, nullptr, "GetWriterLockAccessorEx"},
|
2021-04-07 01:42:31 -04:00
|
|
|
{40, nullptr, "IsSleepEnabled"},
|
|
|
|
{41, nullptr, "IsRebootEnabled"},
|
2018-10-21 16:40:17 -04:00
|
|
|
{100, nullptr, "PopRequestLaunchApplicationForDebug"},
|
2019-11-12 08:54:58 -05:00
|
|
|
{110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
|
|
|
|
{200, nullptr, "LaunchDevMenu"},
|
2021-04-07 01:42:31 -04:00
|
|
|
{1000, nullptr, "SetLastApplicationExitReason"},
|
2018-05-07 11:27:30 -04:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
RegisterHandlers(functions);
|
2020-04-30 21:20:43 -04:00
|
|
|
|
2021-04-09 19:56:11 -04:00
|
|
|
Kernel::KAutoObject::Create(std::addressof(pop_from_general_channel_event));
|
2021-04-04 03:56:09 -04:00
|
|
|
pop_from_general_channel_event.Initialize("IHomeMenuFunctions:PopFromGeneralChannelEvent");
|
2018-05-07 11:27:30 -04:00
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
|
2018-11-26 01:06:13 -05:00
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-04-30 21:20:43 -04:00
|
|
|
void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx) {
|
|
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
|
|
rb.Push(RESULT_SUCCESS);
|
2021-04-04 03:56:09 -04:00
|
|
|
rb.PushCopyObjects(pop_from_general_channel_event.GetReadableEvent());
|
2020-04-30 21:20:43 -04:00
|
|
|
}
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IGlobalStateController::IGlobalStateController(Core::System& system_)
|
|
|
|
: ServiceFramework{system_, "IGlobalStateController"} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-05-07 11:27:30 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, nullptr, "RequestToEnterSleep"},
|
|
|
|
{1, nullptr, "EnterSleep"},
|
|
|
|
{2, nullptr, "StartSleepSequence"},
|
|
|
|
{3, nullptr, "StartShutdownSequence"},
|
|
|
|
{4, nullptr, "StartRebootSequence"},
|
2019-04-10 14:48:37 -04:00
|
|
|
{9, nullptr, "IsAutoPowerDownRequested"},
|
2018-05-07 11:27:30 -04:00
|
|
|
{10, nullptr, "LoadAndApplyIdlePolicySettings"},
|
|
|
|
{11, nullptr, "NotifyCecSettingsChanged"},
|
|
|
|
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
|
|
|
|
{13, nullptr, "UpdateDefaultDisplayResolution"},
|
|
|
|
{14, nullptr, "ShouldSleepOnBoot"},
|
|
|
|
{15, nullptr, "GetHdcpAuthenticationFailedEvent"},
|
2021-04-07 01:44:26 -04:00
|
|
|
{30, nullptr, "OpenCradleFirmwareUpdater"},
|
2018-05-07 11:27:30 -04:00
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IGlobalStateController::~IGlobalStateController() = default;
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IApplicationCreator::IApplicationCreator(Core::System& system_)
|
|
|
|
: ServiceFramework{system_, "IApplicationCreator"} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-05-07 11:27:30 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, nullptr, "CreateApplication"},
|
|
|
|
{1, nullptr, "PopLaunchRequestedApplication"},
|
|
|
|
{10, nullptr, "CreateSystemApplication"},
|
|
|
|
{100, nullptr, "PopFloatingApplicationForDevelopment"},
|
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
|
|
|
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
IApplicationCreator::~IApplicationCreator() = default;
|
|
|
|
|
2020-11-26 15:19:08 -05:00
|
|
|
IProcessWindingController::IProcessWindingController(Core::System& system_)
|
|
|
|
: ServiceFramework{system_, "IProcessWindingController"} {
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format off
|
2018-05-07 11:27:30 -04:00
|
|
|
static const FunctionInfo functions[] = {
|
|
|
|
{0, nullptr, "GetLaunchReason"},
|
|
|
|
{11, nullptr, "OpenCallingLibraryApplet"},
|
|
|
|
{21, nullptr, "PushContext"},
|
|
|
|
{22, nullptr, "PopContext"},
|
|
|
|
{23, nullptr, "CancelWindingReservation"},
|
|
|
|
{30, nullptr, "WindAndDoReserved"},
|
|
|
|
{40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
|
|
|
|
{41, nullptr, "ReserveToStartAndWait"},
|
|
|
|
};
|
2018-10-21 16:40:17 -04:00
|
|
|
// clang-format on
|
|
|
|
|
2018-05-07 11:27:30 -04:00
|
|
|
RegisterHandlers(functions);
|
|
|
|
}
|
hle/service: Default constructors and destructors in the cpp file where applicable
When a destructor isn't defaulted into a cpp file, it can cause the use
of forward declarations to seemingly fail to compile for non-obvious
reasons. It also allows inlining of the construction/destruction logic
all over the place where a constructor or destructor is invoked, which
can lead to code bloat. This isn't so much a worry here, given the
services won't be created and destroyed frequently.
The cause of the above mentioned non-obvious errors can be demonstrated
as follows:
------- Demonstrative example, if you know how the described error happens, skip forwards -------
Assume we have the following in the header, which we'll call "thing.h":
\#include <memory>
// Forward declaration. For example purposes, assume the definition
// of Object is in some header named "object.h"
class Object;
class Thing {
public:
// assume no constructors or destructors are specified here,
// or the constructors/destructors are defined as:
//
// Thing() = default;
// ~Thing() = default;
//
// ... Some interface member functions would be defined here
private:
std::shared_ptr<Object> obj;
};
If this header is included in a cpp file, (which we'll call "main.cpp"),
this will result in a compilation error, because even though no
destructor is specified, the destructor will still need to be generated by
the compiler because std::shared_ptr's destructor is *not* trivial (in
other words, it does something other than nothing), as std::shared_ptr's
destructor needs to do two things:
1. Decrement the shared reference count of the object being pointed to,
and if the reference count decrements to zero,
2. Free the Object instance's memory (aka deallocate the memory it's
pointing to).
And so the compiler generates the code for the destructor doing this inside main.cpp.
Now, keep in mind, the Object forward declaration is not a complete type. All it
does is tell the compiler "a type named Object exists" and allows us to
use the name in certain situations to avoid a header dependency. So the
compiler needs to generate destruction code for Object, but the compiler
doesn't know *how* to destruct it. A forward declaration doesn't tell
the compiler anything about Object's constructor or destructor. So, the
compiler will issue an error in this case because it's undefined
behavior to try and deallocate (or construct) an incomplete type and
std::shared_ptr and std::unique_ptr make sure this isn't the case
internally.
Now, if we had defaulted the destructor in "thing.cpp", where we also
include "object.h", this would never be an issue, as the destructor
would only have its code generated in one place, and it would be in a
place where the full class definition of Object would be visible to the
compiler.
---------------------- End example ----------------------------
Given these service classes are more than certainly going to change in
the future, this defaults the constructors and destructors into the
relevant cpp files to make the construction and destruction of all of
the services consistent and unlikely to run into cases where forward
declarations are indirectly causing compilation errors. It also has the
plus of avoiding the need to rebuild several services if destruction
logic changes, since it would only be necessary to recompile the single
cpp file.
2018-09-10 21:20:52 -04:00
|
|
|
|
|
|
|
IProcessWindingController::~IProcessWindingController() = default;
|
2018-04-19 21:41:44 -04:00
|
|
|
} // namespace Service::AM
|