Compare commits
111 Commits
android-26
...
android-27
Author | SHA1 | Date | |
---|---|---|---|
93e1b78826 | |||
f69a4f53d0 | |||
4c1db495b8 | |||
9b56f9a1a8 | |||
aa76d24901 | |||
dc94882c90 | |||
30567a5909 | |||
f1b1530249 | |||
6948ac8c16 | |||
b2e129eaa5 | |||
1de37306a5 | |||
9bc85dda5f | |||
c7174d5f61 | |||
1bec420695 | |||
79edad2533 | |||
ce62fa6f7b | |||
a0e254e7c4 | |||
25c3bbba0e | |||
d66ca8b731 | |||
fd9ed54f27 | |||
f9bfdb1555 | |||
15831b19a3 | |||
8416d1c028 | |||
4d5d37ae61 | |||
e62cea20d1 | |||
9e27dbb53b | |||
dc50b95a47 | |||
4050242cf3 | |||
fd718f350c | |||
0d6fd12231 | |||
f297e98a9e | |||
637c54e205 | |||
f045fa576b | |||
692ba0fa7d | |||
a93d249ac1 | |||
9fccccedee | |||
ca7f949ee8 | |||
05f94dc5fc | |||
dcf7698924 | |||
7b68d7d467 | |||
4741e50047 | |||
7836c0867d | |||
d1e0039bc8 | |||
7a51eaa727 | |||
6c40d75e47 | |||
0a0c257206 | |||
7019023cbc | |||
c48c182fe0 | |||
98be02898b | |||
e1bdeb2942 | |||
015d666a4d | |||
624c90a439 | |||
0fb26acccc | |||
ed315fb8a5 | |||
fc6a87bba1 | |||
d08f201e0c | |||
0369c65870 | |||
975d6f1ec4 | |||
7c9e2255be | |||
9f6818a6e5 | |||
f1c16b487a | |||
6512f39061 | |||
22b91afa69 | |||
77107ba124 | |||
fa4dec9fe9 | |||
215e887be0 | |||
0da6704fc2 | |||
812754edec | |||
964e19ab56 | |||
9dc624f5dc | |||
dad9ea3e07 | |||
2c00599a53 | |||
2786d34dd7 | |||
864b046500 | |||
c04567fad4 | |||
89c2fd3d28 | |||
5ab49c833d | |||
0e74204aad | |||
a37bd0b9a7 | |||
01d89acd13 | |||
e85466c1ae | |||
352297d361 | |||
6c2d6cff19 | |||
e540757279 | |||
a8bca24292 | |||
5f3c03d6a8 | |||
6b956a6951 | |||
8689370830 | |||
8ffa27b311 | |||
6334616b44 | |||
2e4a6b7f92 | |||
5f90bd88da | |||
c575a85233 | |||
ea4703cb31 | |||
0471e54e5a | |||
6012c9fe3a | |||
f65539504f | |||
62083fcafd | |||
2e5a9cf119 | |||
a45b8bc9bc | |||
a05bd3c47e | |||
2a2c92f181 | |||
f54277364c | |||
b5a17b501b | |||
2b18957365 | |||
4c71bf3d90 | |||
fdf4a5bc90 | |||
b7d9eba72b | |||
380475af32 | |||
a2a0be4246 | |||
aa6532cf34 |
3
.github/workflows/verify.yml
vendored
3
.github/workflows/verify.yml
vendored
@ -81,8 +81,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
# workaround for https://github.com/actions/setup-python/issues/577
|
brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd
|
||||||
brew install autoconf automake boost@1.83 ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd || brew link --overwrite python@3.12
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
|
12
README.md
12
README.md
@ -1,3 +1,15 @@
|
|||||||
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|
|----|----|----|----|----|
|
||||||
|
| [12461](https://github.com/yuzu-emu/yuzu//pull/12461) | [`a84e8e26f`](https://github.com/yuzu-emu/yuzu//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||||
|
| [13018](https://github.com/yuzu-emu/yuzu//pull/13018) | [`01cbc638a`](https://github.com/yuzu-emu/yuzu//pull/13018/files) | am: rewrite part 2 | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
| [13174](https://github.com/yuzu-emu/yuzu//pull/13174) | [`7d1284826`](https://github.com/yuzu-emu/yuzu//pull/13174/files) | glue/time: Remove global variables | [FearlessTobi](https://github.com/FearlessTobi/) | Yes |
|
||||||
|
| [13177](https://github.com/yuzu-emu/yuzu//pull/13177) | [`f5cc94f05`](https://github.com/yuzu-emu/yuzu//pull/13177/files) | vfs: misc performance improvements | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
|
||||||
|
|
||||||
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
7
externals/CMakeLists.txt
vendored
7
externals/CMakeLists.txt
vendored
@ -314,3 +314,10 @@ endif()
|
|||||||
if (NOT TARGET SimpleIni::SimpleIni)
|
if (NOT TARGET SimpleIni::SimpleIni)
|
||||||
add_subdirectory(simpleini)
|
add_subdirectory(simpleini)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# sse2neon
|
||||||
|
if (ARCHITECTURE_arm64 AND NOT TARGET sse2neon)
|
||||||
|
add_library(sse2neon INTERFACE)
|
||||||
|
target_include_directories(sse2neon INTERFACE sse2neon)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
9285
externals/sse2neon/sse2neon.h
vendored
Normal file
9285
externals/sse2neon/sse2neon.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -121,6 +121,7 @@ else()
|
|||||||
-Wno-attributes
|
-Wno-attributes
|
||||||
-Wno-invalid-offsetof
|
-Wno-invalid-offsetof
|
||||||
-Wno-unused-parameter
|
-Wno-unused-parameter
|
||||||
|
-Wno-missing-field-initializers
|
||||||
)
|
)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
|
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
|
||||||
@ -164,6 +165,7 @@ else()
|
|||||||
|
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
add_definitions(-DMINGW_HAS_SECURE_API)
|
add_definitions(-DMINGW_HAS_SECURE_API)
|
||||||
|
add_compile_options("-msse4.1")
|
||||||
|
|
||||||
if (MINGW_STATIC_BUILD)
|
if (MINGW_STATIC_BUILD)
|
||||||
add_definitions(-DQT_STATICPLUGIN)
|
add_definitions(-DQT_STATICPLUGIN)
|
||||||
|
@ -668,7 +668,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
|
|||||||
ASSERT(user_id);
|
ASSERT(user_id);
|
||||||
|
|
||||||
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
||||||
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, 1,
|
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, 1,
|
||||||
user_id->AsU128(), 0);
|
user_id->AsU128(), 0);
|
||||||
|
|
||||||
const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
|
const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
|
||||||
@ -836,8 +836,8 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
|
|||||||
FileSys::OpenMode::Read);
|
FileSys::OpenMode::Read);
|
||||||
|
|
||||||
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
|
||||||
{}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
|
{}, vfsNandDir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, program_id,
|
||||||
program_id, user_id->AsU128(), 0);
|
user_id->AsU128(), 0);
|
||||||
return Common::Android::ToJString(env, user_save_data_path);
|
return Common::Android::ToJString(env, user_save_data_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,16 +73,15 @@ void Manager::BufferReleaseAndRegister() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Manager::GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names,
|
u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names,
|
||||||
[[maybe_unused]] const u32 max_count,
|
|
||||||
[[maybe_unused]] const bool filter) {
|
[[maybe_unused]] const bool filter) {
|
||||||
std::scoped_lock l{mutex};
|
std::scoped_lock l{mutex};
|
||||||
|
|
||||||
LinkToManager();
|
LinkToManager();
|
||||||
|
|
||||||
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
|
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
|
||||||
if (input_devices.size() > 1) {
|
if (!input_devices.empty() && !names.empty()) {
|
||||||
names.emplace_back("Uac");
|
names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -60,13 +60,11 @@ public:
|
|||||||
* Get a list of audio in device names.
|
* Get a list of audio in device names.
|
||||||
*
|
*
|
||||||
* @param names - Output container to write names to.
|
* @param names - Output container to write names to.
|
||||||
* @param max_count - Maximum number of device names to write. Unused
|
|
||||||
* @param filter - Should the list be filtered? Unused.
|
* @param filter - Should the list be filtered? Unused.
|
||||||
*
|
*
|
||||||
* @return Number of names written.
|
* @return Number of names written.
|
||||||
*/
|
*/
|
||||||
u32 GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 max_count,
|
u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
|
||||||
bool filter);
|
|
||||||
|
|
||||||
/// Core system
|
/// Core system
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
@ -146,7 +146,11 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tags[released++] = tag;
|
if (released < tags.size()) {
|
||||||
|
tags[released] = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
released++;
|
||||||
|
|
||||||
if (released >= tags.size()) {
|
if (released >= tags.size()) {
|
||||||
break;
|
break;
|
||||||
|
@ -28,8 +28,8 @@ OpusDecoder::~OpusDecoder() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
|
Result OpusDecoder::Initialize(const OpusParametersEx& params,
|
||||||
u64 transfer_memory_size) {
|
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
|
||||||
auto frame_size{params.use_large_frame_size ? 5760 : 1920};
|
auto frame_size{params.use_large_frame_size ? 5760 : 1920};
|
||||||
shared_buffer_size = transfer_memory_size;
|
shared_buffer_size = transfer_memory_size;
|
||||||
shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
|
shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
|
||||||
@ -59,7 +59,7 @@ Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params,
|
Result OpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
|
||||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
|
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
|
||||||
auto frame_size{params.use_large_frame_size ? 5760 : 1920};
|
auto frame_size{params.use_large_frame_size ? 5760 : 1920};
|
||||||
shared_buffer_size = transfer_memory_size;
|
shared_buffer_size = transfer_memory_size;
|
||||||
|
@ -22,10 +22,10 @@ public:
|
|||||||
explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_);
|
explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_);
|
||||||
~OpusDecoder();
|
~OpusDecoder();
|
||||||
|
|
||||||
Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
|
Result Initialize(const OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
|
||||||
u64 transfer_memory_size);
|
|
||||||
Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
|
|
||||||
u64 transfer_memory_size);
|
u64 transfer_memory_size);
|
||||||
|
Result Initialize(const OpusMultiStreamParametersEx& params,
|
||||||
|
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
|
||||||
Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count,
|
Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count,
|
||||||
std::span<const u8> input_data, std::span<u8> output_data, bool reset);
|
std::span<const u8> input_data, std::span<u8> output_data, bool reset);
|
||||||
Result SetContext([[maybe_unused]] std::span<const u8> context);
|
Result SetContext([[maybe_unused]] std::span<const u8> context);
|
||||||
|
@ -38,7 +38,7 @@ OpusDecoderManager::OpusDecoderManager(Core::System& system_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) {
|
Result OpusDecoderManager::GetWorkBufferSize(const OpusParameters& params, u32& out_size) {
|
||||||
OpusParametersEx ex{
|
OpusParametersEx ex{
|
||||||
.sample_rate = params.sample_rate,
|
.sample_rate = params.sample_rate,
|
||||||
.channel_count = params.channel_count,
|
.channel_count = params.channel_count,
|
||||||
@ -47,11 +47,11 @@ Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_si
|
|||||||
R_RETURN(GetWorkBufferSizeExEx(ex, out_size));
|
R_RETURN(GetWorkBufferSizeExEx(ex, out_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) {
|
Result OpusDecoderManager::GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size) {
|
||||||
R_RETURN(GetWorkBufferSizeExEx(params, out_size));
|
R_RETURN(GetWorkBufferSizeExEx(params, out_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) {
|
Result OpusDecoderManager::GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size) {
|
||||||
R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
|
R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
|
||||||
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
|
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64&
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params,
|
Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params,
|
||||||
u64& out_size) {
|
u32& out_size) {
|
||||||
OpusMultiStreamParametersEx ex{
|
OpusMultiStreamParametersEx ex{
|
||||||
.sample_rate = params.sample_rate,
|
.sample_rate = params.sample_rate,
|
||||||
.channel_count = params.channel_count,
|
.channel_count = params.channel_count,
|
||||||
@ -76,13 +76,13 @@ Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParame
|
|||||||
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size));
|
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params,
|
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
|
||||||
u64& out_size) {
|
const OpusMultiStreamParametersEx& params, u32& out_size) {
|
||||||
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size));
|
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params,
|
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
|
||||||
u64& out_size) {
|
const OpusMultiStreamParametersEx& params, u32& out_size) {
|
||||||
R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
|
R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
|
||||||
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
|
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
|
||||||
R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count,
|
R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count,
|
||||||
|
@ -22,17 +22,19 @@ public:
|
|||||||
return hardware_opus;
|
return hardware_opus;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetWorkBufferSize(OpusParameters& params, u64& out_size);
|
Result GetWorkBufferSize(const OpusParameters& params, u32& out_size);
|
||||||
Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size);
|
Result GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size);
|
||||||
Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size);
|
Result GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size);
|
||||||
Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size);
|
Result GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params, u32& out_size);
|
||||||
Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size);
|
Result GetWorkBufferSizeForMultiStreamEx(const OpusMultiStreamParametersEx& params,
|
||||||
Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size);
|
u32& out_size);
|
||||||
|
Result GetWorkBufferSizeForMultiStreamExEx(const OpusMultiStreamParametersEx& params,
|
||||||
|
u32& out_size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
HardwareOpus hardware_opus;
|
HardwareOpus hardware_opus;
|
||||||
std::array<u64, MaxChannels> required_workbuffer_sizes{};
|
std::array<u32, MaxChannels> required_workbuffer_sizes{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AudioCore::OpusDecoder
|
} // namespace AudioCore::OpusDecoder
|
||||||
|
@ -42,7 +42,7 @@ HardwareOpus::HardwareOpus(Core::System& system_)
|
|||||||
opus_decoder.SetSharedMemory(shared_memory);
|
opus_decoder.SetSharedMemory(shared_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
|
u32 HardwareOpus::GetWorkBufferSize(u32 channel) {
|
||||||
if (!opus_decoder.IsRunning()) {
|
if (!opus_decoder.IsRunning()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -55,10 +55,10 @@ u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
|
|||||||
ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg);
|
ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return shared_memory.dsp_return_data[0];
|
return static_cast<u32>(shared_memory.dsp_return_data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
|
u32 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
|
||||||
std::scoped_lock l{mutex};
|
std::scoped_lock l{mutex};
|
||||||
shared_memory.host_send_data[0] = total_stream_count;
|
shared_memory.host_send_data[0] = total_stream_count;
|
||||||
shared_memory.host_send_data[1] = stereo_stream_count;
|
shared_memory.host_send_data[1] = stereo_stream_count;
|
||||||
@ -70,7 +70,7 @@ u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 st
|
|||||||
ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg);
|
ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return shared_memory.dsp_return_data[0];
|
return static_cast<u32>(shared_memory.dsp_return_data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
|
Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
|
||||||
@ -94,8 +94,9 @@ Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count,
|
|||||||
|
|
||||||
Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
|
Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
|
||||||
u32 total_stream_count,
|
u32 total_stream_count,
|
||||||
u32 stereo_stream_count, void* mappings,
|
u32 stereo_stream_count,
|
||||||
void* buffer, u64 buffer_size) {
|
const void* mappings, void* buffer,
|
||||||
|
u64 buffer_size) {
|
||||||
std::scoped_lock l{mutex};
|
std::scoped_lock l{mutex};
|
||||||
shared_memory.host_send_data[0] = (u64)buffer;
|
shared_memory.host_send_data[0] = (u64)buffer;
|
||||||
shared_memory.host_send_data[1] = buffer_size;
|
shared_memory.host_send_data[1] = buffer_size;
|
||||||
|
@ -16,14 +16,14 @@ class HardwareOpus {
|
|||||||
public:
|
public:
|
||||||
HardwareOpus(Core::System& system);
|
HardwareOpus(Core::System& system);
|
||||||
|
|
||||||
u64 GetWorkBufferSize(u32 channel);
|
u32 GetWorkBufferSize(u32 channel);
|
||||||
u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
|
u32 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
|
||||||
|
|
||||||
Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
|
Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
|
||||||
u64 buffer_size);
|
u64 buffer_size);
|
||||||
Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
|
Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
|
||||||
u32 totaL_stream_count, u32 stereo_stream_count,
|
u32 totaL_stream_count, u32 stereo_stream_count,
|
||||||
void* mappings, void* buffer, u64 buffer_size);
|
const void* mappings, void* buffer, u64 buffer_size);
|
||||||
Result ShutdownDecodeObject(void* buffer, u64 buffer_size);
|
Result ShutdownDecodeObject(void* buffer, u64 buffer_size);
|
||||||
Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size);
|
Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size);
|
||||||
Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size,
|
Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size,
|
||||||
|
@ -20,7 +20,7 @@ struct OpusParametersEx {
|
|||||||
/* 0x00 */ u32 sample_rate;
|
/* 0x00 */ u32 sample_rate;
|
||||||
/* 0x04 */ u32 channel_count;
|
/* 0x04 */ u32 channel_count;
|
||||||
/* 0x08 */ bool use_large_frame_size;
|
/* 0x08 */ bool use_large_frame_size;
|
||||||
/* 0x09 */ INSERT_PADDING_BYTES(7);
|
/* 0x09 */ INSERT_PADDING_BYTES_NOINIT(7);
|
||||||
}; // size = 0x10
|
}; // size = 0x10
|
||||||
static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!");
|
static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!");
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ struct OpusMultiStreamParametersEx {
|
|||||||
/* 0x08 */ u32 total_stream_count;
|
/* 0x08 */ u32 total_stream_count;
|
||||||
/* 0x0C */ u32 stereo_stream_count;
|
/* 0x0C */ u32 stereo_stream_count;
|
||||||
/* 0x10 */ bool use_large_frame_size;
|
/* 0x10 */ bool use_large_frame_size;
|
||||||
/* 0x11 */ INSERT_PADDING_BYTES(7);
|
/* 0x11 */ INSERT_PADDING_BYTES_NOINIT(7);
|
||||||
/* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings;
|
/* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings;
|
||||||
}; // size = 0x118
|
}; // size = 0x118
|
||||||
static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
|
static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
|
||||||
|
@ -36,8 +36,7 @@ AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id
|
|||||||
: output_sink{system.AudioCore().GetOutputSink()},
|
: output_sink{system.AudioCore().GetOutputSink()},
|
||||||
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
|
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
|
||||||
|
|
||||||
u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
|
u32 AudioDevice::ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const {
|
||||||
const size_t max_count) const {
|
|
||||||
std::span<const AudioDeviceName> names{};
|
std::span<const AudioDeviceName> names{};
|
||||||
|
|
||||||
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
|
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
|
||||||
@ -46,19 +45,18 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
|
|||||||
names = device_names;
|
names = device_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 out_count{static_cast<u32>(std::min(max_count, names.size()))};
|
const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), names.size()))};
|
||||||
for (u32 i = 0; i < out_count; i++) {
|
for (u32 i = 0; i < out_count; i++) {
|
||||||
out_buffer.push_back(names[i]);
|
out_buffer[i] = names[i];
|
||||||
}
|
}
|
||||||
return out_count;
|
return out_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 AudioDevice::ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer,
|
u32 AudioDevice::ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const {
|
||||||
const size_t max_count) const {
|
const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), output_device_names.size()))};
|
||||||
const u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
|
|
||||||
|
|
||||||
for (u32 i = 0; i < out_count; i++) {
|
for (u32 i = 0; i < out_count; i++) {
|
||||||
out_buffer.push_back(output_device_names[i]);
|
out_buffer[i] = output_device_names[i];
|
||||||
}
|
}
|
||||||
return out_count;
|
return out_count;
|
||||||
}
|
}
|
||||||
|
@ -36,20 +36,18 @@ public:
|
|||||||
* Get a list of the available output devices.
|
* Get a list of the available output devices.
|
||||||
*
|
*
|
||||||
* @param out_buffer - Output buffer to write the available device names.
|
* @param out_buffer - Output buffer to write the available device names.
|
||||||
* @param max_count - Maximum number of devices to write (count of out_buffer).
|
|
||||||
* @return Number of device names written.
|
* @return Number of device names written.
|
||||||
*/
|
*/
|
||||||
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
|
u32 ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of the available output devices.
|
* Get a list of the available output devices.
|
||||||
* Different to above somehow...
|
* Different to above somehow...
|
||||||
*
|
*
|
||||||
* @param out_buffer - Output buffer to write the available device names.
|
* @param out_buffer - Output buffer to write the available device names.
|
||||||
* @param max_count - Maximum number of devices to write (count of out_buffer).
|
|
||||||
* @return Number of device names written.
|
* @return Number of device names written.
|
||||||
*/
|
*/
|
||||||
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
|
u32 ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the volume of all streams in the backend sink.
|
* Set the volume of all streams in the backend sink.
|
||||||
|
@ -17,9 +17,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
|
|||||||
|
|
||||||
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
|
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
|
||||||
Kernel::KTransferMemory* transfer_memory,
|
Kernel::KTransferMemory* transfer_memory,
|
||||||
const u64 transfer_memory_size, const u32 process_handle,
|
const u64 transfer_memory_size, Kernel::KProcess* process_handle,
|
||||||
Kernel::KProcess& process, const u64 applet_resource_user_id,
|
const u64 applet_resource_user_id, const s32 session_id) {
|
||||||
const s32 session_id) {
|
|
||||||
if (params.execution_mode == ExecutionMode::Auto) {
|
if (params.execution_mode == ExecutionMode::Auto) {
|
||||||
if (!manager.AddSystem(system)) {
|
if (!manager.AddSystem(system)) {
|
||||||
LOG_ERROR(Service_Audio,
|
LOG_ERROR(Service_Audio,
|
||||||
@ -30,7 +29,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
|
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
|
||||||
applet_resource_user_id, session_id);
|
applet_resource_user_id, session_id);
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
@ -38,14 +38,14 @@ public:
|
|||||||
* @param params - Input parameters to initialize the system with.
|
* @param params - Input parameters to initialize the system with.
|
||||||
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
|
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
|
||||||
* @param transfer_memory_size - Size of the transfer memory. Unused.
|
* @param transfer_memory_size - Size of the transfer memory. Unused.
|
||||||
* @param process_handle - Process handle, also used for memory. Unused.
|
* @param process_handle - Process handle, also used for memory.
|
||||||
* @param applet_resource_user_id - Applet id for this renderer. Unused.
|
* @param applet_resource_user_id - Applet id for this renderer. Unused.
|
||||||
* @param session_id - Session id of this renderer.
|
* @param session_id - Session id of this renderer.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result Initialize(const AudioRendererParameterInternal& params,
|
Result Initialize(const AudioRendererParameterInternal& params,
|
||||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||||
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
|
Kernel::KProcess* process_handle, u64 applet_resource_user_id,
|
||||||
s32 session_id);
|
s32 session_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
namespace AudioCore::Renderer {
|
namespace AudioCore::Renderer {
|
||||||
|
|
||||||
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
|
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
|
||||||
const u32 process_handle_, BehaviorInfo& behaviour_)
|
Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
|
||||||
: input{input_.data() + sizeof(UpdateDataHeader)},
|
: input{input_.data() + sizeof(UpdateDataHeader)},
|
||||||
input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
|
input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
|
||||||
output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(
|
output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/service/audio/errors.h"
|
#include "core/hle/service/audio/errors.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KProcess;
|
||||||
|
}
|
||||||
|
|
||||||
namespace AudioCore::Renderer {
|
namespace AudioCore::Renderer {
|
||||||
class BehaviorInfo;
|
class BehaviorInfo;
|
||||||
class VoiceContext;
|
class VoiceContext;
|
||||||
@ -39,8 +43,8 @@ class InfoUpdater {
|
|||||||
static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!");
|
static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit InfoUpdater(std::span<const u8> input, std::span<u8> output, u32 process_handle,
|
explicit InfoUpdater(std::span<const u8> input, std::span<u8> output,
|
||||||
BehaviorInfo& behaviour);
|
Kernel::KProcess* process_handle, BehaviorInfo& behaviour);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the voice channel resources.
|
* Update the voice channel resources.
|
||||||
@ -197,7 +201,7 @@ private:
|
|||||||
/// Expected output size, see CheckConsumedSize
|
/// Expected output size, see CheckConsumedSize
|
||||||
u64 expected_output_size;
|
u64 expected_output_size;
|
||||||
/// Unused
|
/// Unused
|
||||||
u32 process_handle;
|
Kernel::KProcess* process_handle;
|
||||||
/// Behaviour
|
/// Behaviour
|
||||||
BehaviorInfo& behaviour;
|
BehaviorInfo& behaviour;
|
||||||
};
|
};
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
namespace AudioCore::Renderer {
|
namespace AudioCore::Renderer {
|
||||||
|
|
||||||
PoolMapper::PoolMapper(u32 process_handle_, bool force_map_)
|
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, bool force_map_)
|
||||||
: process_handle{process_handle_}, force_map{force_map_} {}
|
: process_handle{process_handle_}, force_map{force_map_} {}
|
||||||
|
|
||||||
PoolMapper::PoolMapper(u32 process_handle_, std::span<MemoryPoolInfo> pool_infos_, u32 pool_count_,
|
PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
|
||||||
bool force_map_)
|
u32 pool_count_, bool force_map_)
|
||||||
: process_handle{process_handle_}, pool_infos{pool_infos_.data()},
|
: process_handle{process_handle_}, pool_infos{pool_infos_.data()},
|
||||||
pool_count{pool_count_}, force_map{force_map_} {}
|
pool_count{pool_count_}, force_map{force_map_} {}
|
||||||
|
|
||||||
@ -106,15 +106,17 @@ bool PoolMapper::IsForceMapEnabled() const {
|
|||||||
return force_map;
|
return force_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
|
Kernel::KProcess* PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
|
||||||
switch (pool->GetLocation()) {
|
switch (pool->GetLocation()) {
|
||||||
case MemoryPoolInfo::Location::CPU:
|
case MemoryPoolInfo::Location::CPU:
|
||||||
return process_handle;
|
return process_handle;
|
||||||
case MemoryPoolInfo::Location::DSP:
|
case MemoryPoolInfo::Location::DSP:
|
||||||
return Kernel::Svc::CurrentProcess;
|
// return Kernel::Svc::CurrentProcess;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!");
|
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!");
|
||||||
return Kernel::Svc::CurrentProcess;
|
// return Kernel::Svc::CurrentProcess;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
|
bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
|
||||||
@ -147,14 +149,14 @@ bool PoolMapper::Unmap([[maybe_unused]] const u32 handle, [[maybe_unused]] const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PoolMapper::Unmap(MemoryPoolInfo& pool) const {
|
bool PoolMapper::Unmap(MemoryPoolInfo& pool) const {
|
||||||
[[maybe_unused]] u32 handle{0};
|
[[maybe_unused]] Kernel::KProcess* handle{};
|
||||||
|
|
||||||
switch (pool.GetLocation()) {
|
switch (pool.GetLocation()) {
|
||||||
case MemoryPoolInfo::Location::CPU:
|
case MemoryPoolInfo::Location::CPU:
|
||||||
handle = process_handle;
|
handle = process_handle;
|
||||||
break;
|
break;
|
||||||
case MemoryPoolInfo::Location::DSP:
|
case MemoryPoolInfo::Location::DSP:
|
||||||
handle = Kernel::Svc::CurrentProcess;
|
// handle = Kernel::Svc::CurrentProcess;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size);
|
// nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size);
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/service/audio/errors.h"
|
#include "core/hle/service/audio/errors.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KProcess;
|
||||||
|
}
|
||||||
|
|
||||||
namespace AudioCore::Renderer {
|
namespace AudioCore::Renderer {
|
||||||
class AddressInfo;
|
class AddressInfo;
|
||||||
|
|
||||||
@ -18,9 +22,9 @@ class AddressInfo;
|
|||||||
*/
|
*/
|
||||||
class PoolMapper {
|
class PoolMapper {
|
||||||
public:
|
public:
|
||||||
explicit PoolMapper(u32 process_handle, bool force_map);
|
explicit PoolMapper(Kernel::KProcess* process_handle, bool force_map);
|
||||||
explicit PoolMapper(u32 process_handle, std::span<MemoryPoolInfo> pool_infos, u32 pool_count,
|
explicit PoolMapper(Kernel::KProcess* process_handle, std::span<MemoryPoolInfo> pool_infos,
|
||||||
bool force_map);
|
u32 pool_count, bool force_map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the usage state for all given pools.
|
* Clear the usage state for all given pools.
|
||||||
@ -98,7 +102,7 @@ public:
|
|||||||
* @return CurrentProcessHandle if location == DSP,
|
* @return CurrentProcessHandle if location == DSP,
|
||||||
* the PoolMapper's process_handle if location == CPU
|
* the PoolMapper's process_handle if location == CPU
|
||||||
*/
|
*/
|
||||||
u32 GetProcessHandle(const MemoryPoolInfo* pool) const;
|
Kernel::KProcess* GetProcessHandle(const MemoryPoolInfo* pool) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map the given region with the given handle. This is a no-op.
|
* Map the given region with the given handle. This is a no-op.
|
||||||
@ -167,7 +171,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/// Process handle for this mapper, used when location == CPU
|
/// Process handle for this mapper, used when location == CPU
|
||||||
u32 process_handle;
|
Kernel::KProcess* process_handle{};
|
||||||
/// List of memory pools assigned to this mapper
|
/// List of memory pools assigned to this mapper
|
||||||
MemoryPoolInfo* pool_infos{};
|
MemoryPoolInfo* pool_infos{};
|
||||||
/// The number of pools
|
/// The number of pools
|
||||||
|
@ -102,8 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
|
|||||||
|
|
||||||
Result System::Initialize(const AudioRendererParameterInternal& params,
|
Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||||
u32 process_handle_, Kernel::KProcess& process_,
|
Kernel::KProcess* process_handle_, u64 applet_resource_user_id_,
|
||||||
u64 applet_resource_user_id_, s32 session_id_) {
|
s32 session_id_) {
|
||||||
if (!CheckValidRevision(params.revision)) {
|
if (!CheckValidRevision(params.revision)) {
|
||||||
return Service::Audio::ResultInvalidRevision;
|
return Service::Audio::ResultInvalidRevision;
|
||||||
}
|
}
|
||||||
@ -119,7 +119,6 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
|||||||
behavior.SetUserLibRevision(params.revision);
|
behavior.SetUserLibRevision(params.revision);
|
||||||
|
|
||||||
process_handle = process_handle_;
|
process_handle = process_handle_;
|
||||||
process = &process_;
|
|
||||||
applet_resource_user_id = applet_resource_user_id_;
|
applet_resource_user_id = applet_resource_user_id_;
|
||||||
session_id = session_id_;
|
session_id = session_id_;
|
||||||
|
|
||||||
@ -132,7 +131,8 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
|||||||
render_device = params.rendering_device;
|
render_device = params.rendering_device;
|
||||||
execution_mode = params.execution_mode;
|
execution_mode = params.execution_mode;
|
||||||
|
|
||||||
process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
|
process_handle->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(),
|
||||||
|
transfer_memory_size);
|
||||||
|
|
||||||
// Note: We're not actually using the transfer memory because it's a pain to code for.
|
// Note: We're not actually using the transfer memory because it's a pain to code for.
|
||||||
// Allocate the memory normally instead and hope the game doesn't try to read anything back
|
// Allocate the memory normally instead and hope the game doesn't try to read anything back
|
||||||
@ -616,7 +616,7 @@ void System::SendCommandToDsp() {
|
|||||||
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
|
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
|
||||||
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
|
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
|
||||||
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
|
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
|
||||||
applet_resource_user_id, process,
|
applet_resource_user_id, process_handle,
|
||||||
reset_command_buffers);
|
reset_command_buffers);
|
||||||
reset_command_buffers = false;
|
reset_command_buffers = false;
|
||||||
command_buffer_size = command_size;
|
command_buffer_size = command_size;
|
||||||
|
@ -74,14 +74,14 @@ public:
|
|||||||
* @param params - Input parameters to initialize the system with.
|
* @param params - Input parameters to initialize the system with.
|
||||||
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
|
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
|
||||||
* @param transfer_memory_size - Size of the transfer memory. Unused.
|
* @param transfer_memory_size - Size of the transfer memory. Unused.
|
||||||
* @param process_handle - Process handle, also used for memory. Unused.
|
* @param process_handle - Process handle, also used for memory.
|
||||||
* @param applet_resource_user_id - Applet id for this renderer. Unused.
|
* @param applet_resource_user_id - Applet id for this renderer. Unused.
|
||||||
* @param session_id - Session id of this renderer.
|
* @param session_id - Session id of this renderer.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result Initialize(const AudioRendererParameterInternal& params,
|
Result Initialize(const AudioRendererParameterInternal& params,
|
||||||
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
|
||||||
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
|
Kernel::KProcess* process_handle, u64 applet_resource_user_id,
|
||||||
s32 session_id);
|
s32 session_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,9 +278,7 @@ private:
|
|||||||
/// Does what locks do
|
/// Does what locks do
|
||||||
std::mutex lock{};
|
std::mutex lock{};
|
||||||
/// Process this audio render is operating within, used for memory reads/writes.
|
/// Process this audio render is operating within, used for memory reads/writes.
|
||||||
Kernel::KProcess* process{};
|
Kernel::KProcess* process_handle{};
|
||||||
/// Handle for the process for this system, unused
|
|
||||||
u32 process_handle{};
|
|
||||||
/// Applet resource id for this system, unused
|
/// Applet resource id for this system, unused
|
||||||
u64 applet_resource_user_id{};
|
u64 applet_resource_user_id{};
|
||||||
/// Controls performance input and output
|
/// Controls performance input and output
|
||||||
|
@ -67,9 +67,13 @@ public:
|
|||||||
oboe::AudioStreamBuilder builder;
|
oboe::AudioStreamBuilder builder;
|
||||||
|
|
||||||
const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream);
|
const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream);
|
||||||
ASSERT(result == oboe::Result::OK);
|
if (result == oboe::Result::OK) {
|
||||||
|
return temp_stream->getChannelCount() >= 6 ? 6 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
return temp_stream->getChannelCount() >= 6 ? 6 : 2;
|
LOG_ERROR(Audio_Sink, "Failed to open {} stream. Using default channel count 2",
|
||||||
|
direction == oboe::Direction::Output ? "output" : "input");
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -343,7 +343,7 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||||
unsigned int line_num, const char* function, const char* format,
|
unsigned int line_num, const char* function, fmt::string_view format,
|
||||||
const fmt::format_args& args) {
|
const fmt::format_args& args) {
|
||||||
if (!initialization_in_progress_suppress_logging) {
|
if (!initialization_in_progress_suppress_logging) {
|
||||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
||||||
|
@ -24,12 +24,12 @@ constexpr const char* TrimSourcePath(std::string_view source) {
|
|||||||
|
|
||||||
/// Logs a message to the global logger, using fmt
|
/// Logs a message to the global logger, using fmt
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||||
unsigned int line_num, const char* function, const char* format,
|
unsigned int line_num, const char* function, fmt::string_view format,
|
||||||
const fmt::format_args& args);
|
const fmt::format_args& args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||||
const char* function, const char* format, const Args&... args) {
|
const char* function, fmt::format_string<Args...> format, const Args&... args) {
|
||||||
FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format,
|
FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format,
|
||||||
fmt::make_format_args(args...));
|
fmt::make_format_args(args...));
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -140,7 +140,7 @@ struct Values {
|
|||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> data_erase_applet_mode{linkage, AppletMode::HLE, "data_erase_applet_mode",
|
Setting<AppletMode> data_erase_applet_mode{linkage, AppletMode::HLE, "data_erase_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> error_applet_mode{linkage, AppletMode::HLE, "error_applet_mode",
|
Setting<AppletMode> error_applet_mode{linkage, AppletMode::LLE, "error_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
Setting<AppletMode> net_connect_applet_mode{linkage, AppletMode::HLE, "net_connect_applet_mode",
|
Setting<AppletMode> net_connect_applet_mode{linkage, AppletMode::HLE, "net_connect_applet_mode",
|
||||||
Category::LibraryApplet};
|
Category::LibraryApplet};
|
||||||
@ -435,8 +435,6 @@ struct Values {
|
|||||||
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
||||||
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
// TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control
|
|
||||||
bool renderer_amdvlk_depth_bias_workaround{};
|
|
||||||
Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
|
Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
|
|
||||||
|
@ -38,6 +38,10 @@ std::string StringFromBuffer(std::span<const u8> data) {
|
|||||||
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
|
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StringFromBuffer(std::span<const char> data) {
|
||||||
|
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
|
||||||
|
}
|
||||||
|
|
||||||
// Turns " hej " into "hej". Also handles tabs.
|
// Turns " hej " into "hej". Also handles tabs.
|
||||||
std::string StripSpaces(const std::string& str) {
|
std::string StripSpaces(const std::string& str) {
|
||||||
const std::size_t s = str.find_first_not_of(" \t\r\n");
|
const std::size_t s = str.find_first_not_of(" \t\r\n");
|
||||||
|
@ -19,6 +19,7 @@ namespace Common {
|
|||||||
[[nodiscard]] std::string ToUpper(std::string str);
|
[[nodiscard]] std::string ToUpper(std::string str);
|
||||||
|
|
||||||
[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
|
[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
|
||||||
|
[[nodiscard]] std::string StringFromBuffer(std::span<const char> data);
|
||||||
|
|
||||||
[[nodiscard]] std::string StripSpaces(const std::string& s);
|
[[nodiscard]] std::string StripSpaces(const std::string& s);
|
||||||
[[nodiscard]] std::string StripQuotes(const std::string& s);
|
[[nodiscard]] std::string StripQuotes(const std::string& s);
|
||||||
|
@ -58,6 +58,7 @@ add_library(core STATIC
|
|||||||
file_sys/fs_operate_range.h
|
file_sys/fs_operate_range.h
|
||||||
file_sys/fs_path.h
|
file_sys/fs_path.h
|
||||||
file_sys/fs_path_utility.h
|
file_sys/fs_path_utility.h
|
||||||
|
file_sys/fs_save_data_types.h
|
||||||
file_sys/fs_string_util.h
|
file_sys/fs_string_util.h
|
||||||
file_sys/fsa/fs_i_directory.h
|
file_sys/fsa/fs_i_directory.h
|
||||||
file_sys/fsa/fs_i_file.h
|
file_sys/fsa/fs_i_file.h
|
||||||
@ -400,14 +401,16 @@ add_library(core STATIC
|
|||||||
hle/service/am/am_types.h
|
hle/service/am/am_types.h
|
||||||
hle/service/am/applet.cpp
|
hle/service/am/applet.cpp
|
||||||
hle/service/am/applet.h
|
hle/service/am/applet.h
|
||||||
|
hle/service/am/applet_manager.cpp
|
||||||
hle/service/am/applet_data_broker.cpp
|
hle/service/am/applet_data_broker.cpp
|
||||||
hle/service/am/applet_data_broker.h
|
hle/service/am/applet_data_broker.h
|
||||||
hle/service/am/applet_manager.cpp
|
|
||||||
hle/service/am/applet_manager.h
|
hle/service/am/applet_manager.h
|
||||||
hle/service/am/applet_message_queue.cpp
|
hle/service/am/button_poller.cpp
|
||||||
hle/service/am/applet_message_queue.h
|
hle/service/am/button_poller.h
|
||||||
hle/service/am/display_layer_manager.cpp
|
hle/service/am/display_layer_manager.cpp
|
||||||
hle/service/am/display_layer_manager.h
|
hle/service/am/display_layer_manager.h
|
||||||
|
hle/service/am/event_observer.cpp
|
||||||
|
hle/service/am/event_observer.h
|
||||||
hle/service/am/frontend/applet_cabinet.cpp
|
hle/service/am/frontend/applet_cabinet.cpp
|
||||||
hle/service/am/frontend/applet_cabinet.h
|
hle/service/am/frontend/applet_cabinet.h
|
||||||
hle/service/am/frontend/applet_controller.cpp
|
hle/service/am/frontend/applet_controller.cpp
|
||||||
@ -433,8 +436,12 @@ add_library(core STATIC
|
|||||||
hle/service/am/hid_registration.h
|
hle/service/am/hid_registration.h
|
||||||
hle/service/am/library_applet_storage.cpp
|
hle/service/am/library_applet_storage.cpp
|
||||||
hle/service/am/library_applet_storage.h
|
hle/service/am/library_applet_storage.h
|
||||||
hle/service/am/process.cpp
|
hle/service/am/lifecycle_manager.cpp
|
||||||
hle/service/am/process.h
|
hle/service/am/lifecycle_manager.h
|
||||||
|
hle/service/am/process_creation.cpp
|
||||||
|
hle/service/am/process_creation.h
|
||||||
|
hle/service/am/process_holder.cpp
|
||||||
|
hle/service/am/process_holder.h
|
||||||
hle/service/am/service/all_system_applet_proxies_service.cpp
|
hle/service/am/service/all_system_applet_proxies_service.cpp
|
||||||
hle/service/am/service/all_system_applet_proxies_service.h
|
hle/service/am/service/all_system_applet_proxies_service.h
|
||||||
hle/service/am/service/applet_common_functions.cpp
|
hle/service/am/service/applet_common_functions.cpp
|
||||||
@ -485,31 +492,45 @@ add_library(core STATIC
|
|||||||
hle/service/am/service/system_applet_proxy.h
|
hle/service/am/service/system_applet_proxy.h
|
||||||
hle/service/am/service/window_controller.cpp
|
hle/service/am/service/window_controller.cpp
|
||||||
hle/service/am/service/window_controller.h
|
hle/service/am/service/window_controller.h
|
||||||
hle/service/aoc/aoc_u.cpp
|
hle/service/am/window_system.cpp
|
||||||
hle/service/aoc/aoc_u.h
|
hle/service/am/window_system.h
|
||||||
|
hle/service/aoc/addon_content_manager.cpp
|
||||||
|
hle/service/aoc/addon_content_manager.h
|
||||||
|
hle/service/aoc/purchase_event_manager.cpp
|
||||||
|
hle/service/aoc/purchase_event_manager.h
|
||||||
hle/service/apm/apm.cpp
|
hle/service/apm/apm.cpp
|
||||||
hle/service/apm/apm.h
|
hle/service/apm/apm.h
|
||||||
hle/service/apm/apm_controller.cpp
|
hle/service/apm/apm_controller.cpp
|
||||||
hle/service/apm/apm_controller.h
|
hle/service/apm/apm_controller.h
|
||||||
hle/service/apm/apm_interface.cpp
|
hle/service/apm/apm_interface.cpp
|
||||||
hle/service/apm/apm_interface.h
|
hle/service/apm/apm_interface.h
|
||||||
hle/service/audio/audin_u.cpp
|
|
||||||
hle/service/audio/audin_u.h
|
|
||||||
hle/service/audio/audio.cpp
|
|
||||||
hle/service/audio/audio.h
|
|
||||||
hle/service/audio/audio_controller.cpp
|
hle/service/audio/audio_controller.cpp
|
||||||
hle/service/audio/audio_controller.h
|
hle/service/audio/audio_controller.h
|
||||||
hle/service/audio/audout_u.cpp
|
hle/service/audio/audio_device.cpp
|
||||||
hle/service/audio/audout_u.h
|
hle/service/audio/audio_device.h
|
||||||
hle/service/audio/audrec_a.cpp
|
hle/service/audio/audio_in_manager.cpp
|
||||||
hle/service/audio/audrec_a.h
|
hle/service/audio/audio_in_manager.h
|
||||||
hle/service/audio/audrec_u.cpp
|
hle/service/audio/audio_in.cpp
|
||||||
hle/service/audio/audrec_u.h
|
hle/service/audio/audio_in.h
|
||||||
hle/service/audio/audren_u.cpp
|
hle/service/audio/audio_out_manager.cpp
|
||||||
hle/service/audio/audren_u.h
|
hle/service/audio/audio_out_manager.h
|
||||||
|
hle/service/audio/audio_out.cpp
|
||||||
|
hle/service/audio/audio_out.h
|
||||||
|
hle/service/audio/audio_renderer_manager.cpp
|
||||||
|
hle/service/audio/audio_renderer_manager.h
|
||||||
|
hle/service/audio/audio_renderer.cpp
|
||||||
|
hle/service/audio/audio_renderer.h
|
||||||
|
hle/service/audio/audio.cpp
|
||||||
|
hle/service/audio/audio.h
|
||||||
hle/service/audio/errors.h
|
hle/service/audio/errors.h
|
||||||
hle/service/audio/hwopus.cpp
|
hle/service/audio/final_output_recorder_manager_for_applet.cpp
|
||||||
hle/service/audio/hwopus.h
|
hle/service/audio/final_output_recorder_manager_for_applet.h
|
||||||
|
hle/service/audio/final_output_recorder_manager.cpp
|
||||||
|
hle/service/audio/final_output_recorder_manager.h
|
||||||
|
hle/service/audio/hardware_opus_decoder_manager.cpp
|
||||||
|
hle/service/audio/hardware_opus_decoder_manager.h
|
||||||
|
hle/service/audio/hardware_opus_decoder.cpp
|
||||||
|
hle/service/audio/hardware_opus_decoder.h
|
||||||
hle/service/bcat/backend/backend.cpp
|
hle/service/bcat/backend/backend.cpp
|
||||||
hle/service/bcat/backend/backend.h
|
hle/service/bcat/backend/backend.h
|
||||||
hle/service/bcat/bcat.cpp
|
hle/service/bcat/bcat.cpp
|
||||||
@ -599,6 +620,10 @@ add_library(core STATIC
|
|||||||
hle/service/filesystem/fsp/fs_i_file.h
|
hle/service/filesystem/fsp/fs_i_file.h
|
||||||
hle/service/filesystem/fsp/fs_i_filesystem.cpp
|
hle/service/filesystem/fsp/fs_i_filesystem.cpp
|
||||||
hle/service/filesystem/fsp/fs_i_filesystem.h
|
hle/service/filesystem/fsp/fs_i_filesystem.h
|
||||||
|
hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
|
||||||
|
hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
|
||||||
|
hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
|
||||||
|
hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
|
||||||
hle/service/filesystem/fsp/fs_i_storage.cpp
|
hle/service/filesystem/fsp/fs_i_storage.cpp
|
||||||
hle/service/filesystem/fsp/fs_i_storage.h
|
hle/service/filesystem/fsp/fs_i_storage.h
|
||||||
hle/service/filesystem/fsp/fsp_ldr.cpp
|
hle/service/filesystem/fsp/fsp_ldr.cpp
|
||||||
@ -607,7 +632,9 @@ add_library(core STATIC
|
|||||||
hle/service/filesystem/fsp/fsp_pr.h
|
hle/service/filesystem/fsp/fsp_pr.h
|
||||||
hle/service/filesystem/fsp/fsp_srv.cpp
|
hle/service/filesystem/fsp/fsp_srv.cpp
|
||||||
hle/service/filesystem/fsp/fsp_srv.h
|
hle/service/filesystem/fsp/fsp_srv.h
|
||||||
hle/service/filesystem/fsp/fsp_util.h
|
hle/service/filesystem/fsp/fsp_types.h
|
||||||
|
hle/service/filesystem/fsp/save_data_transfer_prohibiter.cpp
|
||||||
|
hle/service/filesystem/fsp/save_data_transfer_prohibiter.h
|
||||||
hle/service/filesystem/romfs_controller.cpp
|
hle/service/filesystem/romfs_controller.cpp
|
||||||
hle/service/filesystem/romfs_controller.h
|
hle/service/filesystem/romfs_controller.h
|
||||||
hle/service/filesystem/save_data_controller.cpp
|
hle/service/filesystem/save_data_controller.cpp
|
||||||
@ -649,6 +676,10 @@ add_library(core STATIC
|
|||||||
hle/service/glue/time/worker.h
|
hle/service/glue/time/worker.h
|
||||||
hle/service/grc/grc.cpp
|
hle/service/grc/grc.cpp
|
||||||
hle/service/grc/grc.h
|
hle/service/grc/grc.h
|
||||||
|
hle/service/hid/active_vibration_device_list.cpp
|
||||||
|
hle/service/hid/active_vibration_device_list.h
|
||||||
|
hle/service/hid/applet_resource.cpp
|
||||||
|
hle/service/hid/applet_resource.h
|
||||||
hle/service/hid/hid.cpp
|
hle/service/hid/hid.cpp
|
||||||
hle/service/hid/hid.h
|
hle/service/hid/hid.h
|
||||||
hle/service/hid/hid_debug_server.cpp
|
hle/service/hid/hid_debug_server.cpp
|
||||||
@ -864,8 +895,20 @@ add_library(core STATIC
|
|||||||
hle/service/nvnflinger/ui/graphic_buffer.cpp
|
hle/service/nvnflinger/ui/graphic_buffer.cpp
|
||||||
hle/service/nvnflinger/ui/graphic_buffer.h
|
hle/service/nvnflinger/ui/graphic_buffer.h
|
||||||
hle/service/nvnflinger/window.h
|
hle/service/nvnflinger/window.h
|
||||||
|
hle/service/olsc/daemon_controller.cpp
|
||||||
|
hle/service/olsc/daemon_controller.h
|
||||||
|
hle/service/olsc/native_handle_holder.cpp
|
||||||
|
hle/service/olsc/native_handle_holder.h
|
||||||
|
hle/service/olsc/olsc_service_for_application.cpp
|
||||||
|
hle/service/olsc/olsc_service_for_application.h
|
||||||
|
hle/service/olsc/olsc_service_for_system_service.cpp
|
||||||
|
hle/service/olsc/olsc_service_for_system_service.h
|
||||||
hle/service/olsc/olsc.cpp
|
hle/service/olsc/olsc.cpp
|
||||||
hle/service/olsc/olsc.h
|
hle/service/olsc/olsc.h
|
||||||
|
hle/service/olsc/remote_storage_controller.cpp
|
||||||
|
hle/service/olsc/remote_storage_controller.h
|
||||||
|
hle/service/olsc/transfer_task_list_controller.cpp
|
||||||
|
hle/service/olsc/transfer_task_list_controller.h
|
||||||
hle/service/omm/omm.cpp
|
hle/service/omm/omm.cpp
|
||||||
hle/service/omm/omm.h
|
hle/service/omm/omm.h
|
||||||
hle/service/omm/operation_mode_manager.cpp
|
hle/service/omm/operation_mode_manager.cpp
|
||||||
@ -883,18 +926,39 @@ add_library(core STATIC
|
|||||||
hle/service/os/multi_wait_utils.h
|
hle/service/os/multi_wait_utils.h
|
||||||
hle/service/os/mutex.cpp
|
hle/service/os/mutex.cpp
|
||||||
hle/service/os/mutex.h
|
hle/service/os/mutex.h
|
||||||
|
hle/service/os/process.cpp
|
||||||
|
hle/service/os/process.h
|
||||||
hle/service/pcie/pcie.cpp
|
hle/service/pcie/pcie.cpp
|
||||||
hle/service/pcie/pcie.h
|
hle/service/pcie/pcie.h
|
||||||
|
hle/service/pctl/parental_control_service_factory.cpp
|
||||||
|
hle/service/pctl/parental_control_service_factory.h
|
||||||
|
hle/service/pctl/parental_control_service.cpp
|
||||||
|
hle/service/pctl/parental_control_service.h
|
||||||
hle/service/pctl/pctl.cpp
|
hle/service/pctl/pctl.cpp
|
||||||
hle/service/pctl/pctl.h
|
hle/service/pctl/pctl.h
|
||||||
hle/service/pctl/pctl_module.cpp
|
hle/service/pctl/pctl_results.h
|
||||||
hle/service/pctl/pctl_module.h
|
hle/service/pctl/pctl_types.h
|
||||||
hle/service/pcv/pcv.cpp
|
hle/service/pcv/pcv.cpp
|
||||||
hle/service/pcv/pcv.h
|
hle/service/pcv/pcv.h
|
||||||
hle/service/pm/pm.cpp
|
hle/service/pm/pm.cpp
|
||||||
hle/service/pm/pm.h
|
hle/service/pm/pm.h
|
||||||
hle/service/prepo/prepo.cpp
|
hle/service/prepo/prepo.cpp
|
||||||
hle/service/prepo/prepo.h
|
hle/service/prepo/prepo.h
|
||||||
|
hle/service/psc/ovln/ovln_types.h
|
||||||
|
hle/service/psc/ovln/receiver_service.cpp
|
||||||
|
hle/service/psc/ovln/receiver_service.h
|
||||||
|
hle/service/psc/ovln/receiver.cpp
|
||||||
|
hle/service/psc/ovln/receiver.h
|
||||||
|
hle/service/psc/ovln/sender_service.cpp
|
||||||
|
hle/service/psc/ovln/sender_service.h
|
||||||
|
hle/service/psc/ovln/sender.cpp
|
||||||
|
hle/service/psc/ovln/sender.h
|
||||||
|
hle/service/psc/pm_control.cpp
|
||||||
|
hle/service/psc/pm_control.h
|
||||||
|
hle/service/psc/pm_module.cpp
|
||||||
|
hle/service/psc/pm_module.h
|
||||||
|
hle/service/psc/pm_service.cpp
|
||||||
|
hle/service/psc/pm_service.h
|
||||||
hle/service/psc/psc.cpp
|
hle/service/psc/psc.cpp
|
||||||
hle/service/psc/psc.h
|
hle/service/psc/psc.h
|
||||||
hle/service/psc/time/alarms.cpp
|
hle/service/psc/time/alarms.cpp
|
||||||
@ -997,9 +1061,12 @@ add_library(core STATIC
|
|||||||
hle/service/spl/spl_module.h
|
hle/service/spl/spl_module.h
|
||||||
hle/service/spl/spl_results.h
|
hle/service/spl/spl_results.h
|
||||||
hle/service/spl/spl_types.h
|
hle/service/spl/spl_types.h
|
||||||
|
hle/service/ssl/cert_store.cpp
|
||||||
|
hle/service/ssl/cert_store.h
|
||||||
hle/service/ssl/ssl.cpp
|
hle/service/ssl/ssl.cpp
|
||||||
hle/service/ssl/ssl.h
|
hle/service/ssl/ssl.h
|
||||||
hle/service/ssl/ssl_backend.h
|
hle/service/ssl/ssl_backend.h
|
||||||
|
hle/service/ssl/ssl_types.h
|
||||||
hle/service/usb/usb.cpp
|
hle/service/usb/usb.cpp
|
||||||
hle/service/usb/usb.h
|
hle/service/usb/usb.h
|
||||||
hle/service/vi/application_display_service.cpp
|
hle/service/vi/application_display_service.cpp
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <exception>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -20,7 +19,6 @@
|
|||||||
#include "core/cpu_manager.h"
|
#include "core/cpu_manager.h"
|
||||||
#include "core/debugger/debugger.h"
|
#include "core/debugger/debugger.h"
|
||||||
#include "core/device_memory.h"
|
#include "core/device_memory.h"
|
||||||
#include "core/file_sys/bis_factory.h"
|
|
||||||
#include "core/file_sys/fs_filesystem.h"
|
#include "core/file_sys/fs_filesystem.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "core/file_sys/registered_cache.h"
|
||||||
@ -38,6 +36,7 @@
|
|||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/process_creation.h"
|
||||||
#include "core/hle/service/apm/apm_controller.h"
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/glue/glue_manager.h"
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
@ -72,30 +71,6 @@ MICROPROFILE_DEFINE(ARM_CPU3, "ARM", "CPU 3", MP_RGB(255, 64, 64));
|
|||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
FileSys::StorageId GetStorageIdForFrontendSlot(
|
|
||||||
std::optional<FileSys::ContentProviderUnionSlot> slot) {
|
|
||||||
if (!slot.has_value()) {
|
|
||||||
return FileSys::StorageId::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (*slot) {
|
|
||||||
case FileSys::ContentProviderUnionSlot::UserNAND:
|
|
||||||
return FileSys::StorageId::NandUser;
|
|
||||||
case FileSys::ContentProviderUnionSlot::SysNAND:
|
|
||||||
return FileSys::StorageId::NandSystem;
|
|
||||||
case FileSys::ContentProviderUnionSlot::SDMC:
|
|
||||||
return FileSys::StorageId::SdCard;
|
|
||||||
case FileSys::ContentProviderUnionSlot::FrontendManual:
|
|
||||||
return FileSys::StorageId::Host;
|
|
||||||
default:
|
|
||||||
return FileSys::StorageId::None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Anonymous namespace
|
|
||||||
|
|
||||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||||
const std::string& path) {
|
const std::string& path) {
|
||||||
// To account for split 00+01+etc files.
|
// To account for split 00+01+etc files.
|
||||||
@ -297,9 +272,6 @@ struct System::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
||||||
/// Reset all glue registrations
|
|
||||||
arp_manager.ResetAll();
|
|
||||||
|
|
||||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||||
|
|
||||||
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
|
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
|
||||||
@ -335,33 +307,17 @@ struct System::Impl {
|
|||||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||||
const std::string& filepath,
|
const std::string& filepath,
|
||||||
Service::AM::FrontendAppletParameters& params) {
|
Service::AM::FrontendAppletParameters& params) {
|
||||||
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
|
|
||||||
params.program_id, params.program_index);
|
|
||||||
|
|
||||||
if (!app_loader) {
|
|
||||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
|
||||||
return SystemResultStatus::ErrorGetLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
|
|
||||||
LOG_ERROR(Core, "Failed to find title id for ROM!");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name = "Unknown program";
|
|
||||||
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
|
|
||||||
LOG_ERROR(Core, "Failed to read title for ROM!");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO(Core, "Loading {} ({})", name, params.program_id);
|
|
||||||
|
|
||||||
InitializeKernel(system);
|
InitializeKernel(system);
|
||||||
|
|
||||||
// Create the application process.
|
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
|
||||||
auto main_process = Kernel::KProcess::Create(system.Kernel());
|
|
||||||
Kernel::KProcess::Register(system.Kernel(), main_process);
|
// Create the application process
|
||||||
kernel.AppendNewProcess(main_process);
|
Loader::ResultStatus load_result{};
|
||||||
kernel.MakeApplicationProcess(main_process);
|
std::vector<u8> control;
|
||||||
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
|
auto process =
|
||||||
|
Service::AM::CreateApplicationProcess(control, app_loader, load_result, system, file,
|
||||||
|
params.program_id, params.program_index);
|
||||||
|
|
||||||
if (load_result != Loader::ResultStatus::Success) {
|
if (load_result != Loader::ResultStatus::Success) {
|
||||||
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
|
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
|
||||||
ShutdownMainProcess();
|
ShutdownMainProcess();
|
||||||
@ -370,6 +326,25 @@ struct System::Impl {
|
|||||||
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
|
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!app_loader) {
|
||||||
|
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||||
|
return SystemResultStatus::ErrorGetLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
|
||||||
|
LOG_ERROR(Core, "Failed to find program id for ROM!");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name = "Unknown program";
|
||||||
|
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
|
||||||
|
LOG_ERROR(Core, "Failed to read title for ROM!");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(Core, "Loading {} ({:016X}) ...", name, params.program_id);
|
||||||
|
|
||||||
|
// Make the process created be the application
|
||||||
|
kernel.MakeApplicationProcess(process->GetHandle());
|
||||||
|
|
||||||
// Set up the rest of the system.
|
// Set up the rest of the system.
|
||||||
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
|
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
|
||||||
if (init_result != SystemResultStatus::Success) {
|
if (init_result != SystemResultStatus::Success) {
|
||||||
@ -379,7 +354,6 @@ struct System::Impl {
|
|||||||
return init_result;
|
return init_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
|
||||||
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
||||||
|
|
||||||
// Initialize cheat engine
|
// Initialize cheat engine
|
||||||
@ -387,14 +361,9 @@ struct System::Impl {
|
|||||||
cheat_engine->Initialize();
|
cheat_engine->Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register with applet manager.
|
// Register with applet manager
|
||||||
applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(),
|
// All threads are started, begin main process execution, now that we're in the clear
|
||||||
params);
|
applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params);
|
||||||
|
|
||||||
// All threads are started, begin main process execution, now that we're in the clear.
|
|
||||||
main_process->Run(load_parameters->main_thread_priority,
|
|
||||||
load_parameters->main_thread_stack_size);
|
|
||||||
main_process->Close();
|
|
||||||
|
|
||||||
if (Settings::values.gamecard_inserted) {
|
if (Settings::values.gamecard_inserted) {
|
||||||
if (Settings::values.gamecard_current_game) {
|
if (Settings::values.gamecard_current_game) {
|
||||||
@ -425,11 +394,6 @@ struct System::Impl {
|
|||||||
room_member->SendGameInfo(game_info);
|
room_member->SendGameInfo(game_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workarounds:
|
|
||||||
// Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK
|
|
||||||
Settings::values.renderer_amdvlk_depth_bias_workaround =
|
|
||||||
params.program_id == 0x1006A800016E000ULL;
|
|
||||||
|
|
||||||
status = SystemResultStatus::Success;
|
status = SystemResultStatus::Success;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -466,7 +430,6 @@ struct System::Impl {
|
|||||||
kernel.SuspendEmulation(true);
|
kernel.SuspendEmulation(true);
|
||||||
kernel.CloseServices();
|
kernel.CloseServices();
|
||||||
kernel.ShutdownCores();
|
kernel.ShutdownCores();
|
||||||
applet_manager.Reset();
|
|
||||||
services.reset();
|
services.reset();
|
||||||
service_manager.reset();
|
service_manager.reset();
|
||||||
fs_controller.Reset();
|
fs_controller.Reset();
|
||||||
@ -489,8 +452,8 @@ struct System::Impl {
|
|||||||
room_member->SendGameInfo(game_info);
|
room_member->SendGameInfo(game_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workarounds
|
// Reset all glue registrations
|
||||||
Settings::values.renderer_amdvlk_depth_bias_workaround = false;
|
arp_manager.ResetAll();
|
||||||
|
|
||||||
LOG_DEBUG(Core, "Shutdown OK");
|
LOG_DEBUG(Core, "Shutdown OK");
|
||||||
}
|
}
|
||||||
@ -509,31 +472,6 @@ struct System::Impl {
|
|||||||
return app_loader->ReadTitle(out);
|
return app_loader->ReadTitle(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::KProcess& process) {
|
|
||||||
std::vector<u8> nacp_data;
|
|
||||||
FileSys::NACP nacp;
|
|
||||||
if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) {
|
|
||||||
nacp_data = nacp.GetRawBytes();
|
|
||||||
} else {
|
|
||||||
nacp_data.resize(sizeof(FileSys::RawNACP));
|
|
||||||
}
|
|
||||||
|
|
||||||
Service::Glue::ApplicationLaunchProperty launch{};
|
|
||||||
launch.title_id = process.GetProgramId();
|
|
||||||
|
|
||||||
FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider};
|
|
||||||
launch.version = pm.GetGameVersion().value_or(0);
|
|
||||||
|
|
||||||
// TODO(DarkLordZach): When FSController/Game Card Support is added, if
|
|
||||||
// current_process_game_card use correct StorageId
|
|
||||||
launch.base_game_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry(
|
|
||||||
launch.title_id, FileSys::ContentRecordType::Program));
|
|
||||||
launch.update_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry(
|
|
||||||
FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program));
|
|
||||||
|
|
||||||
arp_manager.Register(launch.title_id, launch, std::move(nacp_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetStatus(SystemResultStatus new_status, const char* details = nullptr) {
|
void SetStatus(SystemResultStatus new_status, const char* details = nullptr) {
|
||||||
status = new_status;
|
status = new_status;
|
||||||
if (details) {
|
if (details) {
|
||||||
|
@ -43,6 +43,8 @@ public:
|
|||||||
DeviceMemoryManager(const DeviceMemory& device_memory);
|
DeviceMemoryManager(const DeviceMemory& device_memory);
|
||||||
~DeviceMemoryManager();
|
~DeviceMemoryManager();
|
||||||
|
|
||||||
|
static constexpr bool HAS_FLUSH_INVALIDATION = true;
|
||||||
|
|
||||||
void BindInterface(DeviceInterface* device_inter);
|
void BindInterface(DeviceInterface* device_inter);
|
||||||
|
|
||||||
DAddr Allocate(size_t size);
|
DAddr Allocate(size_t size);
|
||||||
|
188
src/core/file_sys/fs_save_data_types.h
Normal file
188
src/core/file_sys/fs_save_data_types.h
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace FileSys {
|
||||||
|
|
||||||
|
using SaveDataId = u64;
|
||||||
|
using SystemSaveDataId = u64;
|
||||||
|
using SystemBcatSaveDataId = SystemSaveDataId;
|
||||||
|
using ProgramId = u64;
|
||||||
|
|
||||||
|
enum class SaveDataSpaceId : u8 {
|
||||||
|
System = 0,
|
||||||
|
User = 1,
|
||||||
|
SdSystem = 2,
|
||||||
|
Temporary = 3,
|
||||||
|
SdUser = 4,
|
||||||
|
|
||||||
|
ProperSystem = 100,
|
||||||
|
SafeMode = 101,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SaveDataType : u8 {
|
||||||
|
System = 0,
|
||||||
|
Account = 1,
|
||||||
|
Bcat = 2,
|
||||||
|
Device = 3,
|
||||||
|
Temporary = 4,
|
||||||
|
Cache = 5,
|
||||||
|
SystemBcat = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SaveDataRank : u8 {
|
||||||
|
Primary = 0,
|
||||||
|
Secondary = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SaveDataSize {
|
||||||
|
u64 normal;
|
||||||
|
u64 journal;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SaveDataSize) == 0x10, "SaveDataSize has invalid size.");
|
||||||
|
|
||||||
|
using UserId = u128;
|
||||||
|
static_assert(std::is_trivially_copyable_v<UserId>, "Data type must be trivially copyable.");
|
||||||
|
static_assert(sizeof(UserId) == 0x10, "UserId has invalid size.");
|
||||||
|
|
||||||
|
constexpr inline SystemSaveDataId InvalidSystemSaveDataId = 0;
|
||||||
|
constexpr inline UserId InvalidUserId = {};
|
||||||
|
|
||||||
|
enum class SaveDataFlags : u32 {
|
||||||
|
None = (0 << 0),
|
||||||
|
KeepAfterResettingSystemSaveData = (1 << 0),
|
||||||
|
KeepAfterRefurbishment = (1 << 1),
|
||||||
|
KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
|
||||||
|
NeedsSecureDelete = (1 << 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SaveDataMetaType : u8 {
|
||||||
|
None = 0,
|
||||||
|
Thumbnail = 1,
|
||||||
|
ExtensionContext = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SaveDataMetaInfo {
|
||||||
|
u32 size;
|
||||||
|
SaveDataMetaType type;
|
||||||
|
INSERT_PADDING_BYTES(0xB);
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_copyable_v<SaveDataMetaInfo>,
|
||||||
|
"Data type must be trivially copyable.");
|
||||||
|
static_assert(sizeof(SaveDataMetaInfo) == 0x10, "SaveDataMetaInfo has invalid size.");
|
||||||
|
|
||||||
|
struct SaveDataCreationInfo {
|
||||||
|
s64 size;
|
||||||
|
s64 journal_size;
|
||||||
|
s64 block_size;
|
||||||
|
u64 owner_id;
|
||||||
|
u32 flags;
|
||||||
|
SaveDataSpaceId space_id;
|
||||||
|
bool pseudo;
|
||||||
|
INSERT_PADDING_BYTES(0x1A);
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_copyable_v<SaveDataCreationInfo>,
|
||||||
|
"Data type must be trivially copyable.");
|
||||||
|
static_assert(sizeof(SaveDataCreationInfo) == 0x40, "SaveDataCreationInfo has invalid size.");
|
||||||
|
|
||||||
|
struct SaveDataAttribute {
|
||||||
|
ProgramId program_id;
|
||||||
|
UserId user_id;
|
||||||
|
SystemSaveDataId system_save_data_id;
|
||||||
|
SaveDataType type;
|
||||||
|
SaveDataRank rank;
|
||||||
|
u16 index;
|
||||||
|
INSERT_PADDING_BYTES(0x1C);
|
||||||
|
|
||||||
|
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
|
||||||
|
SystemSaveDataId system_save_data_id, u16 index,
|
||||||
|
SaveDataRank rank) {
|
||||||
|
return {
|
||||||
|
.program_id = program_id,
|
||||||
|
.user_id = user_id,
|
||||||
|
.system_save_data_id = system_save_data_id,
|
||||||
|
.type = type,
|
||||||
|
.rank = rank,
|
||||||
|
.index = index,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
|
||||||
|
SystemSaveDataId system_save_data_id, u16 index) {
|
||||||
|
return Make(program_id, type, user_id, system_save_data_id, index, SaveDataRank::Primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
|
||||||
|
SystemSaveDataId system_save_data_id) {
|
||||||
|
return Make(program_id, type, user_id, system_save_data_id, 0, SaveDataRank::Primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DebugInfo() const {
|
||||||
|
return fmt::format(
|
||||||
|
"[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
|
||||||
|
"rank={}, index={}]",
|
||||||
|
program_id, user_id[1], user_id[0], system_save_data_id, static_cast<u8>(type),
|
||||||
|
static_cast<u8>(rank), index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SaveDataAttribute) == 0x40);
|
||||||
|
static_assert(std::is_trivially_destructible<SaveDataAttribute>::value);
|
||||||
|
|
||||||
|
constexpr inline bool operator<(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
|
||||||
|
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.index, lhs.rank) <
|
||||||
|
std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.index, rhs.rank);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool operator==(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
|
||||||
|
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.type, lhs.rank,
|
||||||
|
lhs.index) == std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id,
|
||||||
|
rhs.type, rhs.rank, rhs.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline bool operator!=(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SaveDataExtraData {
|
||||||
|
SaveDataAttribute attr;
|
||||||
|
u64 owner_id;
|
||||||
|
s64 timestamp;
|
||||||
|
u32 flags;
|
||||||
|
INSERT_PADDING_BYTES(4);
|
||||||
|
s64 available_size;
|
||||||
|
s64 journal_size;
|
||||||
|
s64 commit_id;
|
||||||
|
INSERT_PADDING_BYTES(0x190);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has invalid size.");
|
||||||
|
static_assert(std::is_trivially_copyable_v<SaveDataExtraData>,
|
||||||
|
"Data type must be trivially copyable.");
|
||||||
|
|
||||||
|
struct SaveDataFilter {
|
||||||
|
bool use_program_id;
|
||||||
|
bool use_save_data_type;
|
||||||
|
bool use_user_id;
|
||||||
|
bool use_save_data_id;
|
||||||
|
bool use_index;
|
||||||
|
SaveDataRank rank;
|
||||||
|
SaveDataAttribute attribute;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SaveDataFilter) == 0x48, "SaveDataFilter has invalid size.");
|
||||||
|
static_assert(std::is_trivially_copyable_v<SaveDataFilter>,
|
||||||
|
"Data type must be trivially copyable.");
|
||||||
|
|
||||||
|
struct HashSalt {
|
||||||
|
static constexpr size_t Size = 32;
|
||||||
|
|
||||||
|
std::array<u8, Size> value;
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
|
||||||
|
static_assert(sizeof(HashSalt) == HashSalt::Size);
|
||||||
|
|
||||||
|
} // namespace FileSys
|
@ -31,8 +31,8 @@ AesXtsStorage::AesXtsStorage(VirtualFile base, const void* key1, const void* key
|
|||||||
ASSERT(iv_size == IvSize);
|
ASSERT(iv_size == IvSize);
|
||||||
ASSERT(Common::IsAligned(m_block_size, AesBlockSize));
|
ASSERT(Common::IsAligned(m_block_size, AesBlockSize));
|
||||||
|
|
||||||
std::memcpy(m_key.data() + 0, key1, KeySize);
|
std::memcpy(m_key.data() + 0, key1, KeySize / 2);
|
||||||
std::memcpy(m_key.data() + 0x10, key2, KeySize);
|
std::memcpy(m_key.data() + 0x10, key2, KeySize / 2);
|
||||||
std::memcpy(m_iv.data(), iv, IvSize);
|
std::memcpy(m_iv.data(), iv, IvSize);
|
||||||
|
|
||||||
m_cipher.emplace(m_key, Core::Crypto::Mode::XTS);
|
m_cipher.emplace(m_key, Core::Crypto::Mode::XTS);
|
||||||
|
@ -105,12 +105,4 @@ VirtualDir PartitionFilesystem::GetParentDirectory() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartitionFilesystem::PrintDebugInfo() const {
|
|
||||||
LOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic);
|
|
||||||
LOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries);
|
|
||||||
for (u32 i = 0; i < pfs_header.num_entries; i++) {
|
|
||||||
LOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes)", i,
|
|
||||||
pfs_files[i]->GetName(), pfs_files[i]->GetSize());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
std::vector<VirtualDir> GetSubdirectories() const override;
|
std::vector<VirtualDir> GetSubdirectories() const override;
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
VirtualDir GetParentDirectory() const override;
|
VirtualDir GetParentDirectory() const override;
|
||||||
void PrintDebugInfo() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Header {
|
struct Header {
|
||||||
|
@ -14,48 +14,11 @@ namespace FileSys {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void PrintSaveDataAttributeWarnings(SaveDataAttribute meta) {
|
|
||||||
if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
|
|
||||||
if (meta.zero_1 != 0) {
|
|
||||||
LOG_WARNING(Service_FS,
|
|
||||||
"Possibly incorrect SaveDataAttribute, type is "
|
|
||||||
"SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).",
|
|
||||||
meta.zero_1);
|
|
||||||
}
|
|
||||||
if (meta.zero_2 != 0) {
|
|
||||||
LOG_WARNING(Service_FS,
|
|
||||||
"Possibly incorrect SaveDataAttribute, type is "
|
|
||||||
"SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).",
|
|
||||||
meta.zero_2);
|
|
||||||
}
|
|
||||||
if (meta.zero_3 != 0) {
|
|
||||||
LOG_WARNING(Service_FS,
|
|
||||||
"Possibly incorrect SaveDataAttribute, type is "
|
|
||||||
"SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).",
|
|
||||||
meta.zero_3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) {
|
|
||||||
LOG_WARNING(Service_FS,
|
|
||||||
"Possibly incorrect SaveDataAttribute, type is SystemSaveData but title_id is "
|
|
||||||
"non-zero ({:016X}).",
|
|
||||||
meta.title_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) {
|
|
||||||
LOG_WARNING(Service_FS,
|
|
||||||
"Possibly incorrect SaveDataAttribute, type is DeviceSaveData but user_id is "
|
|
||||||
"non-zero ({:016X}{:016X})",
|
|
||||||
meta.user_id[1], meta.user_id[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) {
|
bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) {
|
||||||
return attr.type == SaveDataType::CacheStorage || attr.type == SaveDataType::TemporaryStorage ||
|
return attr.type == SaveDataType::Cache || attr.type == SaveDataType::Temporary ||
|
||||||
(space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User
|
(space == SaveDataSpaceId::User && ///< Normal Save Data -- Current Title & User
|
||||||
(attr.type == SaveDataType::SaveData || attr.type == SaveDataType::DeviceSaveData) &&
|
(attr.type == SaveDataType::Account || attr.type == SaveDataType::Device) &&
|
||||||
attr.title_id == 0 && attr.save_id == 0);
|
attr.program_id == 0 && attr.system_save_data_id == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id,
|
std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id,
|
||||||
@ -63,7 +26,7 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
|
|||||||
// Only detect nand user saves.
|
// Only detect nand user saves.
|
||||||
const auto space_id_path = [space_id]() -> std::string_view {
|
const auto space_id_path = [space_id]() -> std::string_view {
|
||||||
switch (space_id) {
|
switch (space_id) {
|
||||||
case SaveDataSpaceId::NandUser:
|
case SaveDataSpaceId::User:
|
||||||
return "/user/save";
|
return "/user/save";
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
@ -79,9 +42,9 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
|
|||||||
|
|
||||||
// Only detect account/device saves from the future location.
|
// Only detect account/device saves from the future location.
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SaveDataType::SaveData:
|
case SaveDataType::Account:
|
||||||
return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id);
|
return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id);
|
||||||
case SaveDataType::DeviceSaveData:
|
case SaveDataType::Device:
|
||||||
return fmt::format("{}/device/{:016X}/0", space_id_path, title_id);
|
return fmt::format("{}/device/{:016X}/0", space_id_path, title_id);
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
@ -90,13 +53,6 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
|
|||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::string SaveDataAttribute::DebugInfo() const {
|
|
||||||
return fmt::format("[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
|
|
||||||
"rank={}, index={}]",
|
|
||||||
title_id, user_id[1], user_id[0], save_id, static_cast<u8>(type),
|
|
||||||
static_cast<u8>(rank), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
|
SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
|
||||||
VirtualDir save_directory_)
|
VirtualDir save_directory_)
|
||||||
: system{system_}, program_id{program_id_}, dir{std::move(save_directory_)} {
|
: system{system_}, program_id{program_id_}, dir{std::move(save_directory_)} {
|
||||||
@ -108,18 +64,16 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
|
|||||||
SaveDataFactory::~SaveDataFactory() = default;
|
SaveDataFactory::~SaveDataFactory() = default;
|
||||||
|
|
||||||
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
||||||
PrintSaveDataAttributeWarnings(meta);
|
const auto save_directory = GetFullPath(program_id, dir, space, meta.type, meta.program_id,
|
||||||
|
meta.user_id, meta.system_save_data_id);
|
||||||
const auto save_directory =
|
|
||||||
GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
|
||||||
|
|
||||||
return dir->CreateDirectoryRelative(save_directory);
|
return dir->CreateDirectoryRelative(save_directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
|
||||||
|
|
||||||
const auto save_directory =
|
const auto save_directory = GetFullPath(program_id, dir, space, meta.type, meta.program_id,
|
||||||
GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
|
meta.user_id, meta.system_save_data_id);
|
||||||
|
|
||||||
auto out = dir->GetDirectoryRelative(save_directory);
|
auto out = dir->GetDirectoryRelative(save_directory);
|
||||||
|
|
||||||
@ -136,11 +90,11 @@ VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) con
|
|||||||
|
|
||||||
std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
|
std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
|
||||||
switch (space) {
|
switch (space) {
|
||||||
case SaveDataSpaceId::NandSystem:
|
case SaveDataSpaceId::System:
|
||||||
return "/system/";
|
return "/system/";
|
||||||
case SaveDataSpaceId::NandUser:
|
case SaveDataSpaceId::User:
|
||||||
return "/user/";
|
return "/user/";
|
||||||
case SaveDataSpaceId::TemporaryStorage:
|
case SaveDataSpaceId::Temporary:
|
||||||
return "/temp/";
|
return "/temp/";
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space));
|
ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space));
|
||||||
@ -153,7 +107,7 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
|
|||||||
u128 user_id, u64 save_id) {
|
u128 user_id, u64 save_id) {
|
||||||
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
|
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
|
||||||
// be interpreted as the title id of the current process.
|
// be interpreted as the title id of the current process.
|
||||||
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
|
if (type == SaveDataType::Account || type == SaveDataType::Device) {
|
||||||
if (title_id == 0) {
|
if (title_id == 0) {
|
||||||
title_id = program_id;
|
title_id = program_id;
|
||||||
}
|
}
|
||||||
@ -173,16 +127,16 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
|
|||||||
std::string out = GetSaveDataSpaceIdPath(space);
|
std::string out = GetSaveDataSpaceIdPath(space);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SaveDataType::SystemSaveData:
|
case SaveDataType::System:
|
||||||
return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]);
|
return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]);
|
||||||
case SaveDataType::SaveData:
|
case SaveDataType::Account:
|
||||||
case SaveDataType::DeviceSaveData:
|
case SaveDataType::Device:
|
||||||
return fmt::format("{}save/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
|
return fmt::format("{}save/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
|
||||||
title_id);
|
title_id);
|
||||||
case SaveDataType::TemporaryStorage:
|
case SaveDataType::Temporary:
|
||||||
return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
|
return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
|
||||||
title_id);
|
title_id);
|
||||||
case SaveDataType::CacheStorage:
|
case SaveDataType::Cache:
|
||||||
return fmt::format("{}save/cache/{:016X}", out, title_id);
|
return fmt::format("{}save/cache/{:016X}", out, title_id);
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type));
|
ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type));
|
||||||
@ -202,7 +156,7 @@ std::string SaveDataFactory::GetUserGameSaveDataRoot(u128 user_id, bool future)
|
|||||||
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
|
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
|
||||||
u128 user_id) const {
|
u128 user_id) const {
|
||||||
const auto path =
|
const auto path =
|
||||||
GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
|
GetFullPath(program_id, dir, SaveDataSpaceId::User, type, title_id, user_id, 0);
|
||||||
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
||||||
|
|
||||||
const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName());
|
const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName());
|
||||||
@ -221,7 +175,7 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
|
|||||||
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
|
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
|
||||||
SaveDataSize new_value) const {
|
SaveDataSize new_value) const {
|
||||||
const auto path =
|
const auto path =
|
||||||
GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
|
GetFullPath(program_id, dir, SaveDataSpaceId::User, type, title_id, user_id, 0);
|
||||||
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
|
||||||
|
|
||||||
const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName());
|
const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName());
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "core/file_sys/fs_save_data_types.h"
|
||||||
#include "core/file_sys/vfs/vfs.h"
|
#include "core/file_sys/vfs/vfs.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
@ -16,73 +17,6 @@ class System;
|
|||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
enum class SaveDataSpaceId : u8 {
|
|
||||||
NandSystem = 0,
|
|
||||||
NandUser = 1,
|
|
||||||
SdCardSystem = 2,
|
|
||||||
TemporaryStorage = 3,
|
|
||||||
SdCardUser = 4,
|
|
||||||
ProperSystem = 100,
|
|
||||||
SafeMode = 101,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SaveDataType : u8 {
|
|
||||||
SystemSaveData = 0,
|
|
||||||
SaveData = 1,
|
|
||||||
BcatDeliveryCacheStorage = 2,
|
|
||||||
DeviceSaveData = 3,
|
|
||||||
TemporaryStorage = 4,
|
|
||||||
CacheStorage = 5,
|
|
||||||
SystemBcat = 6,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SaveDataRank : u8 {
|
|
||||||
Primary = 0,
|
|
||||||
Secondary = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SaveDataFlags : u32 {
|
|
||||||
None = (0 << 0),
|
|
||||||
KeepAfterResettingSystemSaveData = (1 << 0),
|
|
||||||
KeepAfterRefurbishment = (1 << 1),
|
|
||||||
KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
|
|
||||||
NeedsSecureDelete = (1 << 3),
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SaveDataAttribute {
|
|
||||||
u64 title_id;
|
|
||||||
u128 user_id;
|
|
||||||
u64 save_id;
|
|
||||||
SaveDataType type;
|
|
||||||
SaveDataRank rank;
|
|
||||||
u16 index;
|
|
||||||
INSERT_PADDING_BYTES_NOINIT(4);
|
|
||||||
u64 zero_1;
|
|
||||||
u64 zero_2;
|
|
||||||
u64 zero_3;
|
|
||||||
|
|
||||||
std::string DebugInfo() const;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(SaveDataAttribute) == 0x40, "SaveDataAttribute has incorrect size.");
|
|
||||||
|
|
||||||
struct SaveDataExtraData {
|
|
||||||
SaveDataAttribute attr;
|
|
||||||
u64 owner_id;
|
|
||||||
s64 timestamp;
|
|
||||||
SaveDataFlags flags;
|
|
||||||
INSERT_PADDING_BYTES_NOINIT(4);
|
|
||||||
s64 available_size;
|
|
||||||
s64 journal_size;
|
|
||||||
s64 commit_id;
|
|
||||||
std::array<u8, 0x190> unused;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has incorrect size.");
|
|
||||||
|
|
||||||
struct SaveDataSize {
|
|
||||||
u64 normal;
|
|
||||||
u64 journal;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr const char* GetSaveDataSizeFileName() {
|
constexpr const char* GetSaveDataSizeFileName() {
|
||||||
return ".yuzu_save_size";
|
return ".yuzu_save_size";
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
OffsetVfsFile::OffsetVfsFile(VirtualFile file_, std::size_t size_, std::size_t offset_,
|
OffsetVfsFile::OffsetVfsFile(VirtualFile file_, std::size_t size_, std::size_t offset_,
|
||||||
std::string name_, VirtualDir parent_)
|
std::string name_)
|
||||||
: file(file_), offset(offset_), size(size_), name(std::move(name_)),
|
: file(file_), offset(offset_), size(size_), name(std::move(name_)) {}
|
||||||
parent(parent_ == nullptr ? file->GetContainingDirectory() : std::move(parent_)) {}
|
|
||||||
|
|
||||||
OffsetVfsFile::~OffsetVfsFile() = default;
|
OffsetVfsFile::~OffsetVfsFile() = default;
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ bool OffsetVfsFile::Resize(std::size_t new_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VirtualDir OffsetVfsFile::GetContainingDirectory() const {
|
VirtualDir OffsetVfsFile::GetContainingDirectory() const {
|
||||||
return parent;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OffsetVfsFile::IsWritable() const {
|
bool OffsetVfsFile::IsWritable() const {
|
||||||
|
@ -16,7 +16,7 @@ namespace FileSys {
|
|||||||
class OffsetVfsFile : public VfsFile {
|
class OffsetVfsFile : public VfsFile {
|
||||||
public:
|
public:
|
||||||
OffsetVfsFile(VirtualFile file, std::size_t size, std::size_t offset = 0,
|
OffsetVfsFile(VirtualFile file, std::size_t size, std::size_t offset = 0,
|
||||||
std::string new_name = "", VirtualDir new_parent = nullptr);
|
std::string new_name = "");
|
||||||
~OffsetVfsFile() override;
|
~OffsetVfsFile() override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
@ -44,7 +44,6 @@ private:
|
|||||||
std::size_t offset;
|
std::size_t offset;
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
std::string name;
|
std::string name;
|
||||||
VirtualDir parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
@ -76,6 +76,7 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size,
|
VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size,
|
||||||
|
std::optional<std::string> parent_path,
|
||||||
OpenMode perms) {
|
OpenMode perms) {
|
||||||
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
||||||
std::scoped_lock lk{list_lock};
|
std::scoped_lock lk{list_lock};
|
||||||
@ -94,14 +95,14 @@ VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::op
|
|||||||
this->InsertReferenceIntoListLocked(*reference);
|
this->InsertReferenceIntoListLocked(*reference);
|
||||||
|
|
||||||
auto file = std::shared_ptr<RealVfsFile>(
|
auto file = std::shared_ptr<RealVfsFile>(
|
||||||
new RealVfsFile(*this, std::move(reference), path, perms, size));
|
new RealVfsFile(*this, std::move(reference), path, perms, size, std::move(parent_path)));
|
||||||
cache[path] = file;
|
cache[path] = file;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, OpenMode perms) {
|
VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, OpenMode perms) {
|
||||||
return OpenFileFromEntry(path_, {}, perms);
|
return OpenFileFromEntry(path_, {}, {}, perms);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, OpenMode perms) {
|
VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, OpenMode perms) {
|
||||||
@ -268,10 +269,11 @@ void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
|
RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
|
||||||
const std::string& path_, OpenMode perms_, std::optional<u64> size_)
|
const std::string& path_, OpenMode perms_, std::optional<u64> size_,
|
||||||
|
std::optional<std::string> parent_path_)
|
||||||
: base(base_), reference(std::move(reference_)), path(path_),
|
: base(base_), reference(std::move(reference_)), path(path_),
|
||||||
parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponentsCopy(path_)),
|
parent_path(parent_path_ ? std::move(*parent_path_) : FS::GetParentPath(path_)),
|
||||||
size(size_), perms(perms_) {}
|
path_components(FS::SplitPathComponentsCopy(path_)), size(size_), perms(perms_) {}
|
||||||
|
|
||||||
RealVfsFile::~RealVfsFile() {
|
RealVfsFile::~RealVfsFile() {
|
||||||
base.DropReference(std::move(reference));
|
base.DropReference(std::move(reference));
|
||||||
@ -348,7 +350,7 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(
|
|||||||
&out](const std::filesystem::directory_entry& entry) {
|
&out](const std::filesystem::directory_entry& entry) {
|
||||||
const auto full_path_string = FS::PathToUTF8String(entry.path());
|
const auto full_path_string = FS::PathToUTF8String(entry.path());
|
||||||
|
|
||||||
out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms));
|
out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), path, perms));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -62,6 +62,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
friend class RealVfsDirectory;
|
friend class RealVfsDirectory;
|
||||||
VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size,
|
VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size,
|
||||||
|
std::optional<std::string> parent_path,
|
||||||
OpenMode perms = OpenMode::Read);
|
OpenMode perms = OpenMode::Read);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -91,7 +92,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
|
RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
|
||||||
const std::string& path, OpenMode perms = OpenMode::Read,
|
const std::string& path, OpenMode perms = OpenMode::Read,
|
||||||
std::optional<u64> size = {});
|
std::optional<u64> size = {}, std::optional<std::string> parent_path = {});
|
||||||
|
|
||||||
RealVfsFilesystem& base;
|
RealVfsFilesystem& base;
|
||||||
std::unique_ptr<FileReference> reference;
|
std::unique_ptr<FileReference> reference;
|
||||||
|
@ -44,15 +44,32 @@ public:
|
|||||||
GuestMemory() = delete;
|
GuestMemory() = delete;
|
||||||
explicit GuestMemory(M& memory, u64 addr, std::size_t size,
|
explicit GuestMemory(M& memory, u64 addr, std::size_t size,
|
||||||
Common::ScratchBuffer<T>* backup = nullptr)
|
Common::ScratchBuffer<T>* backup = nullptr)
|
||||||
: m_memory{memory}, m_addr{addr}, m_size{size} {
|
: m_memory{&memory}, m_addr{addr}, m_size{size} {
|
||||||
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
|
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
||||||
|
if (!this->TrySetSpan()) {
|
||||||
|
if (backup) {
|
||||||
|
backup->resize_destructive(this->size());
|
||||||
|
m_data_span = *backup;
|
||||||
|
m_span_valid = true;
|
||||||
|
m_is_data_copy = true;
|
||||||
|
} else {
|
||||||
|
m_data_copy.resize(this->size());
|
||||||
|
m_data_span = std::span(m_data_copy);
|
||||||
|
m_span_valid = true;
|
||||||
|
m_is_data_copy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
||||||
Read(addr, size, backup);
|
Read(addr, size, backup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~GuestMemory() = default;
|
~GuestMemory() = default;
|
||||||
|
|
||||||
|
GuestMemory(GuestMemory&& rhs) = default;
|
||||||
|
GuestMemory& operator=(GuestMemory&& rhs) = default;
|
||||||
|
|
||||||
T* data() noexcept {
|
T* data() noexcept {
|
||||||
return m_data_span.data();
|
return m_data_span.data();
|
||||||
}
|
}
|
||||||
@ -109,8 +126,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->TrySetSpan()) {
|
if (this->TrySetSpan()) {
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
if constexpr (FLAGS & GuestMemoryFlags::Safe && M::HAS_FLUSH_INVALIDATION) {
|
||||||
m_memory.FlushRegion(m_addr, this->size_bytes());
|
m_memory->FlushRegion(m_addr, this->size_bytes());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (backup) {
|
if (backup) {
|
||||||
@ -123,9 +140,9 @@ public:
|
|||||||
m_is_data_copy = true;
|
m_is_data_copy = true;
|
||||||
m_span_valid = true;
|
m_span_valid = true;
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
|
m_memory->ReadBlock(m_addr, this->data(), this->size_bytes());
|
||||||
} else {
|
} else {
|
||||||
m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
|
m_memory->ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_data_span;
|
return m_data_span;
|
||||||
@ -133,18 +150,19 @@ public:
|
|||||||
|
|
||||||
void Write(std::span<T> write_data) noexcept {
|
void Write(std::span<T> write_data) noexcept {
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||||
m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
|
m_memory->WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
|
||||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
|
m_memory->WriteBlock(m_addr, write_data.data(), this->size_bytes());
|
||||||
} else {
|
} else {
|
||||||
m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
|
m_memory->WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrySetSpan() noexcept {
|
bool TrySetSpan() noexcept {
|
||||||
if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
|
if (u8* ptr = m_memory->GetSpan(m_addr, this->size_bytes()); ptr) {
|
||||||
m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
|
m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
|
||||||
m_span_valid = true;
|
m_span_valid = true;
|
||||||
|
m_is_data_copy = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -159,7 +177,7 @@ protected:
|
|||||||
return m_addr_changed;
|
return m_addr_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
M& m_memory;
|
M* m_memory;
|
||||||
u64 m_addr{};
|
u64 m_addr{};
|
||||||
size_t m_size{};
|
size_t m_size{};
|
||||||
std::span<T> m_data_span{};
|
std::span<T> m_data_span{};
|
||||||
@ -175,17 +193,7 @@ public:
|
|||||||
GuestMemoryScoped() = delete;
|
GuestMemoryScoped() = delete;
|
||||||
explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
|
explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
|
||||||
Common::ScratchBuffer<T>* backup = nullptr)
|
Common::ScratchBuffer<T>* backup = nullptr)
|
||||||
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
|
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {}
|
||||||
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
|
||||||
if (!this->TrySetSpan()) {
|
|
||||||
if (backup) {
|
|
||||||
this->m_data_span = *backup;
|
|
||||||
this->m_span_valid = true;
|
|
||||||
this->m_is_data_copy = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~GuestMemoryScoped() {
|
~GuestMemoryScoped() {
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Write) {
|
if constexpr (FLAGS & GuestMemoryFlags::Write) {
|
||||||
@ -196,15 +204,17 @@ public:
|
|||||||
if (this->AddressChanged() || this->IsDataCopy()) {
|
if (this->AddressChanged() || this->IsDataCopy()) {
|
||||||
ASSERT(this->m_span_valid);
|
ASSERT(this->m_span_valid);
|
||||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||||
this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
|
this->m_memory->WriteBlockCached(this->m_addr, this->data(),
|
||||||
|
this->size_bytes());
|
||||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||||
this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
||||||
} else {
|
} else {
|
||||||
this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
|
this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(),
|
||||||
|
this->size_bytes());
|
||||||
}
|
}
|
||||||
} else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
|
} else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
|
||||||
(FLAGS & GuestMemoryFlags::Cached)) {
|
(FLAGS & GuestMemoryFlags::Cached)) {
|
||||||
this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
|
this->m_memory->InvalidateRegion(this->m_addr, this->size_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1170,6 +1170,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
|
|||||||
// Determine if we are an application.
|
// Determine if we are an application.
|
||||||
if (pool == KMemoryManager::Pool::Application) {
|
if (pool == KMemoryManager::Pool::Application) {
|
||||||
flag |= Svc::CreateProcessFlag::IsApplication;
|
flag |= Svc::CreateProcessFlag::IsApplication;
|
||||||
|
m_is_application = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are 64-bit, create as such.
|
// If we are 64-bit, create as such.
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#include "core/hle/service/acc/async_context.h"
|
#include "core/hle/service/acc/async_context.h"
|
||||||
#include "core/hle/service/acc/errors.h"
|
#include "core/hle/service/acc/errors.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
#include "core/hle/service/glue/glue_manager.h"
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
|
|
||||||
@ -74,12 +74,12 @@ static void SanitizeJPEGImageSize(std::vector<u8>& image) {
|
|||||||
|
|
||||||
class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
|
class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
|
||||||
public:
|
public:
|
||||||
explicit IManagerForSystemService(Core::System& system_, Common::UUID)
|
explicit IManagerForSystemService(Core::System& system_, Common::UUID uuid)
|
||||||
: ServiceFramework{system_, "IManagerForSystemService"} {
|
: ServiceFramework{system_, "IManagerForSystemService"}, account_id{uuid} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IManagerForSystemService::CheckAvailability, "CheckAvailability"},
|
{0, D<&IManagerForSystemService::CheckAvailability>, "CheckAvailability"},
|
||||||
{1, nullptr, "GetAccountId"},
|
{1, D<&IManagerForSystemService::GetAccountId>, "GetAccountId"},
|
||||||
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
||||||
{3, nullptr, "LoadIdTokenCache"},
|
{3, nullptr, "LoadIdTokenCache"},
|
||||||
{100, nullptr, "SetSystemProgramIdentification"},
|
{100, nullptr, "SetSystemProgramIdentification"},
|
||||||
@ -109,11 +109,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CheckAvailability(HLERequestContext& ctx) {
|
Result CheckAvailability() {
|
||||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
R_SUCCEED();
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result GetAccountId(Out<u64> out_account_id) {
|
||||||
|
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||||
|
*out_account_id = account_id.Hash();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::UUID account_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3.0.0+
|
// 3.0.0+
|
||||||
|
@ -23,7 +23,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
|
|||||||
{99, nullptr, "DebugActivateOpenContextRetention"},
|
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||||
{100, nullptr, "GetUserRegistrationNotifier"},
|
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||||
{101, nullptr, "GetUserStateChangeNotifier"},
|
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||||
{102, nullptr, "GetBaasAccountManagerForSystemService"},
|
{102, &ACC_U1::GetBaasAccountManagerForSystemService, "GetBaasAccountManagerForSystemService"},
|
||||||
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||||
{104, nullptr, "GetProfileUpdateNotifier"},
|
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||||
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||||
|
@ -2,19 +2,26 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
|
#include "core/hle/service/am/button_poller.h"
|
||||||
|
#include "core/hle/service/am/event_observer.h"
|
||||||
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
||||||
#include "core/hle/service/am/service/application_proxy_service.h"
|
#include "core/hle/service/am/service/application_proxy_service.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
void LoopProcess(Core::System& system) {
|
void LoopProcess(Core::System& system) {
|
||||||
|
WindowSystem window_system(system);
|
||||||
|
ButtonPoller button_poller(system, window_system);
|
||||||
|
EventObserver event_observer(system, window_system);
|
||||||
|
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
server_manager->RegisterNamedService("appletAE",
|
server_manager->RegisterNamedService(
|
||||||
std::make_shared<IAllSystemAppletProxiesService>(system));
|
"appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, window_system));
|
||||||
server_manager->RegisterNamedService("appletOE",
|
server_manager->RegisterNamedService(
|
||||||
std::make_shared<IApplicationProxyService>(system));
|
"appletOE", std::make_shared<IApplicationProxyService>(system, window_system));
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ namespace Service::AM {
|
|||||||
|
|
||||||
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
|
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
|
||||||
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
||||||
|
constexpr Result ResultLibraryAppletTerminated{ErrorModule::AM, 22};
|
||||||
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
||||||
constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511};
|
constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511};
|
||||||
constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512};
|
constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512};
|
||||||
|
@ -48,11 +48,6 @@ enum class SystemButtonType {
|
|||||||
CaptureButtonLongPressing,
|
CaptureButtonLongPressing,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SysPlatformRegion : s32 {
|
|
||||||
Global = 1,
|
|
||||||
Terra = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AppletProcessLaunchReason {
|
struct AppletProcessLaunchReason {
|
||||||
u8 flag;
|
u8 flag;
|
||||||
INSERT_PADDING_BYTES(3);
|
INSERT_PADDING_BYTES(3);
|
||||||
@ -66,12 +61,6 @@ enum class ScreenshotPermission : u32 {
|
|||||||
Disable = 2,
|
Disable = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FocusHandlingMode {
|
|
||||||
bool notify;
|
|
||||||
bool background;
|
|
||||||
bool suspend;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class IdleTimeDetectionExtension : u32 {
|
enum class IdleTimeDetectionExtension : u32 {
|
||||||
Disabled = 0,
|
Disabled = 0,
|
||||||
Extended = 1,
|
Extended = 1,
|
||||||
@ -244,7 +233,6 @@ struct ApplicationPlayStatistics {
|
|||||||
static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
|
static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
|
||||||
"ApplicationPlayStatistics has incorrect size.");
|
"ApplicationPlayStatistics has incorrect size.");
|
||||||
|
|
||||||
using AppletResourceUserId = u64;
|
|
||||||
using ProgramId = u64;
|
using ProgramId = u64;
|
||||||
|
|
||||||
struct Applet;
|
struct Applet;
|
||||||
|
@ -1,27 +1,71 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/scope_exit.h"
|
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/service/am/am_results.h"
|
|
||||||
#include "core/hle/service/am/applet.h"
|
#include "core/hle/service/am/applet.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
Applet::Applet(Core::System& system, std::unique_ptr<Process> process_)
|
Applet::Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_application)
|
||||||
: context(system, "Applet"), message_queue(system), process(std::move(process_)),
|
: context(system, "Applet"), lifecycle_manager(system, context, is_application),
|
||||||
hid_registration(system, *process), gpu_error_detected_event(context),
|
process(std::move(process_)), hid_registration(system, *process),
|
||||||
friend_invitation_storage_channel_event(context), notification_storage_channel_event(context),
|
gpu_error_detected_event(context), friend_invitation_storage_channel_event(context),
|
||||||
health_warning_disappeared_system_event(context), acquired_sleep_lock_event(context),
|
notification_storage_channel_event(context), health_warning_disappeared_system_event(context),
|
||||||
pop_from_general_channel_event(context), library_applet_launchable_event(context),
|
acquired_sleep_lock_event(context), pop_from_general_channel_event(context),
|
||||||
accumulated_suspended_tick_changed_event(context), sleep_lock_event(context) {
|
library_applet_launchable_event(context), accumulated_suspended_tick_changed_event(context),
|
||||||
|
sleep_lock_event(context), state_changed_event(context) {
|
||||||
|
|
||||||
aruid = process->GetProcessId();
|
aruid.pid = process->GetProcessId();
|
||||||
program_id = process->GetProgramId();
|
program_id = process->GetProgramId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Applet::~Applet() = default;
|
Applet::~Applet() = default;
|
||||||
|
|
||||||
|
void Applet::UpdateSuspensionStateLocked(bool force_message) {
|
||||||
|
// Remove any forced resumption.
|
||||||
|
lifecycle_manager.RemoveForceResumeIfPossible();
|
||||||
|
|
||||||
|
// Check if we're runnable.
|
||||||
|
const bool curr_activity_runnable = lifecycle_manager.IsRunnable();
|
||||||
|
const bool prev_activity_runnable = is_activity_runnable;
|
||||||
|
const bool was_changed = curr_activity_runnable != prev_activity_runnable;
|
||||||
|
|
||||||
|
if (was_changed) {
|
||||||
|
if (curr_activity_runnable) {
|
||||||
|
process->Suspend(false);
|
||||||
|
} else {
|
||||||
|
process->Suspend(true);
|
||||||
|
lifecycle_manager.RequestResumeNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
is_activity_runnable = curr_activity_runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lifecycle_manager.GetForcedSuspend()) {
|
||||||
|
// TODO: why is this allowed?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal if the focus state was changed or the process state was changed.
|
||||||
|
if (lifecycle_manager.UpdateRequestedFocusState() || was_changed || force_message) {
|
||||||
|
lifecycle_manager.SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Applet::SetInteractibleLocked(bool interactible) {
|
||||||
|
if (is_interactible == interactible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_interactible = interactible;
|
||||||
|
|
||||||
|
hid_registration.EnableAppletToGetInput(interactible && !lifecycle_manager.GetExitRequested());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Applet::OnProcessTerminatedLocked() {
|
||||||
|
is_completed = true;
|
||||||
|
state_changed_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -3,25 +3,28 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
#include "core/hle/service/apm/apm_controller.h"
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
#include "core/hle/service/caps/caps_types.h"
|
#include "core/hle/service/caps/caps_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
#include "core/hle/service/os/event.h"
|
#include "core/hle/service/os/event.h"
|
||||||
|
#include "core/hle/service/os/process.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
#include "core/hle/service/am/am_types.h"
|
#include "core/hle/service/am/am_types.h"
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
|
||||||
#include "core/hle/service/am/display_layer_manager.h"
|
#include "core/hle/service/am/display_layer_manager.h"
|
||||||
#include "core/hle/service/am/hid_registration.h"
|
#include "core/hle/service/am/hid_registration.h"
|
||||||
#include "core/hle/service/am/process.h"
|
#include "core/hle/service/am/lifecycle_manager.h"
|
||||||
|
#include "core/hle/service/am/process_holder.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
struct Applet {
|
struct Applet {
|
||||||
explicit Applet(Core::System& system, std::unique_ptr<Process> process_);
|
explicit Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_application);
|
||||||
~Applet();
|
~Applet();
|
||||||
|
|
||||||
// Lock
|
// Lock
|
||||||
@ -30,11 +33,13 @@ struct Applet {
|
|||||||
// Event creation helper
|
// Event creation helper
|
||||||
KernelHelpers::ServiceContext context;
|
KernelHelpers::ServiceContext context;
|
||||||
|
|
||||||
// Applet message queue
|
// Lifecycle manager
|
||||||
AppletMessageQueue message_queue;
|
LifecycleManager lifecycle_manager;
|
||||||
|
|
||||||
// Process
|
// Process
|
||||||
std::unique_ptr<Process> process;
|
std::unique_ptr<Process> process;
|
||||||
|
std::optional<ProcessHolder> process_holder;
|
||||||
|
bool is_process_running{};
|
||||||
|
|
||||||
// Creation state
|
// Creation state
|
||||||
AppletId applet_id{};
|
AppletId applet_id{};
|
||||||
@ -75,11 +80,9 @@ struct Applet {
|
|||||||
bool game_play_recording_supported{};
|
bool game_play_recording_supported{};
|
||||||
GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
|
GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
|
||||||
bool jit_service_launched{};
|
bool jit_service_launched{};
|
||||||
bool is_running{};
|
|
||||||
bool application_crash_report_enabled{};
|
bool application_crash_report_enabled{};
|
||||||
|
|
||||||
// Common state
|
// Common state
|
||||||
FocusState focus_state{};
|
|
||||||
bool sleep_lock_enabled{};
|
bool sleep_lock_enabled{};
|
||||||
bool vr_mode_enabled{};
|
bool vr_mode_enabled{};
|
||||||
bool lcd_backlight_off_enabled{};
|
bool lcd_backlight_off_enabled{};
|
||||||
@ -93,15 +96,12 @@ struct Applet {
|
|||||||
// Caller applet
|
// Caller applet
|
||||||
std::weak_ptr<Applet> caller_applet{};
|
std::weak_ptr<Applet> caller_applet{};
|
||||||
std::shared_ptr<AppletDataBroker> caller_applet_broker{};
|
std::shared_ptr<AppletDataBroker> caller_applet_broker{};
|
||||||
|
std::list<std::shared_ptr<Applet>> child_applets{};
|
||||||
|
bool is_completed{};
|
||||||
|
|
||||||
// Self state
|
// Self state
|
||||||
bool exit_locked{};
|
bool exit_locked{};
|
||||||
s32 fatal_section_count{};
|
s32 fatal_section_count{};
|
||||||
bool operation_mode_changed_notification_enabled{true};
|
|
||||||
bool performance_mode_changed_notification_enabled{true};
|
|
||||||
FocusHandlingMode focus_handling_mode{};
|
|
||||||
bool restart_message_enabled{};
|
|
||||||
bool out_of_focus_suspension_enabled{true};
|
|
||||||
Capture::AlbumImageOrientation album_image_orientation{};
|
Capture::AlbumImageOrientation album_image_orientation{};
|
||||||
bool handles_request_to_display{};
|
bool handles_request_to_display{};
|
||||||
ScreenshotPermission screenshot_permission{};
|
ScreenshotPermission screenshot_permission{};
|
||||||
@ -110,6 +110,9 @@ struct Applet {
|
|||||||
u64 suspended_ticks{};
|
u64 suspended_ticks{};
|
||||||
bool album_image_taken_notification_enabled{};
|
bool album_image_taken_notification_enabled{};
|
||||||
bool record_volume_muted{};
|
bool record_volume_muted{};
|
||||||
|
bool is_activity_runnable{};
|
||||||
|
bool is_interactible{true};
|
||||||
|
bool window_visible{true};
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
Event gpu_error_detected_event;
|
Event gpu_error_detected_event;
|
||||||
@ -121,9 +124,15 @@ struct Applet {
|
|||||||
Event library_applet_launchable_event;
|
Event library_applet_launchable_event;
|
||||||
Event accumulated_suspended_tick_changed_event;
|
Event accumulated_suspended_tick_changed_event;
|
||||||
Event sleep_lock_event;
|
Event sleep_lock_event;
|
||||||
|
Event state_changed_event;
|
||||||
|
|
||||||
// Frontend state
|
// Frontend state
|
||||||
std::shared_ptr<Frontend::FrontendApplet> frontend{};
|
std::shared_ptr<Frontend::FrontendApplet> frontend{};
|
||||||
|
|
||||||
|
// Process state management
|
||||||
|
void UpdateSuspensionStateLocked(bool force_message);
|
||||||
|
void SetInteractibleLocked(bool interactible);
|
||||||
|
void OnProcessTerminatedLocked();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -44,24 +44,8 @@ Kernel::KReadableEvent* AppletStorageChannel::GetEvent() {
|
|||||||
|
|
||||||
AppletDataBroker::AppletDataBroker(Core::System& system_)
|
AppletDataBroker::AppletDataBroker(Core::System& system_)
|
||||||
: system(system_), context(system_, "AppletDataBroker"), in_data(context),
|
: system(system_), context(system_, "AppletDataBroker"), in_data(context),
|
||||||
interactive_in_data(context), out_data(context), interactive_out_data(context),
|
interactive_in_data(context), out_data(context), interactive_out_data(context) {}
|
||||||
state_changed_event(context), is_completed(false) {}
|
|
||||||
|
|
||||||
AppletDataBroker::~AppletDataBroker() = default;
|
AppletDataBroker::~AppletDataBroker() = default;
|
||||||
|
|
||||||
void AppletDataBroker::SignalCompletion() {
|
|
||||||
{
|
|
||||||
std::scoped_lock lk{lock};
|
|
||||||
|
|
||||||
if (is_completed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_completed = true;
|
|
||||||
state_changed_event.Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
system.GetAppletManager().FocusStateChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -53,16 +53,6 @@ public:
|
|||||||
return interactive_out_data;
|
return interactive_out_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Event& GetStateChangedEvent() {
|
|
||||||
return state_changed_event;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsCompleted() const {
|
|
||||||
return is_completed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalCompletion();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
KernelHelpers::ServiceContext context;
|
KernelHelpers::ServiceContext context;
|
||||||
@ -71,10 +61,6 @@ private:
|
|||||||
AppletStorageChannel interactive_in_data;
|
AppletStorageChannel interactive_in_data;
|
||||||
AppletStorageChannel out_data;
|
AppletStorageChannel out_data;
|
||||||
AppletStorageChannel interactive_out_data;
|
AppletStorageChannel interactive_out_data;
|
||||||
Event state_changed_event;
|
|
||||||
|
|
||||||
std::mutex lock;
|
|
||||||
bool is_completed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
||||||
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
||||||
#include "core/hle/service/am/service/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
@ -225,49 +226,46 @@ void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& chan
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AppletManager::AppletManager(Core::System& system) : m_system(system) {}
|
AppletManager::AppletManager(Core::System& system) : m_system(system) {}
|
||||||
AppletManager::~AppletManager() {
|
AppletManager::~AppletManager() = default;
|
||||||
this->Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) {
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
m_applets.emplace(applet->aruid, std::move(applet));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
|
|
||||||
std::shared_ptr<Applet> applet;
|
|
||||||
bool should_stop = false;
|
|
||||||
{
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
const auto it = m_applets.find(aruid);
|
|
||||||
if (it == m_applets.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
applet = it->second;
|
|
||||||
m_applets.erase(it);
|
|
||||||
|
|
||||||
should_stop = m_applets.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate process.
|
|
||||||
applet->process->Terminate();
|
|
||||||
|
|
||||||
// If there were no applets left, stop emulation.
|
|
||||||
if (should_stop) {
|
|
||||||
m_system.Exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||||
AppletResourceUserId aruid, const FrontendAppletParameters& params) {
|
std::unique_ptr<Process> process, const FrontendAppletParameters& params) {
|
||||||
// TODO: this should be run inside AM so that the events will have a parent process
|
{
|
||||||
// TODO: have am create the guest process
|
std::scoped_lock lk{m_lock};
|
||||||
auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system));
|
m_pending_process = std::move(process);
|
||||||
|
m_pending_parameters = params;
|
||||||
|
}
|
||||||
|
m_cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::RequestExit() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
if (m_window_system) {
|
||||||
|
m_window_system->OnExitRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::OperationModeChanged() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
if (m_window_system) {
|
||||||
|
m_window_system->OnOperationModeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::SetWindowSystem(WindowSystem* window_system) {
|
||||||
|
std::unique_lock lk{m_lock};
|
||||||
|
|
||||||
|
m_window_system = window_system;
|
||||||
|
if (!m_window_system) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cv.wait(lk, [&] { return m_pending_process != nullptr; });
|
||||||
|
|
||||||
|
const auto& params = m_pending_parameters;
|
||||||
|
auto applet = std::make_shared<Applet>(m_system, std::move(m_pending_process),
|
||||||
|
params.applet_id == AppletId::Application);
|
||||||
|
|
||||||
applet->aruid = aruid;
|
|
||||||
applet->program_id = params.program_id;
|
applet->program_id = params.program_id;
|
||||||
applet->applet_id = params.applet_id;
|
applet->applet_id = params.applet_id;
|
||||||
applet->type = params.applet_type;
|
applet->type = params.applet_type;
|
||||||
@ -322,59 +320,19 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Applet was started by frontend, so it is foreground.
|
// Applet was started by frontend, so it is foreground.
|
||||||
applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
|
applet->lifecycle_manager.SetFocusState(FocusState::InFocus);
|
||||||
applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
|
|
||||||
applet->focus_state = FocusState::InFocus;
|
|
||||||
|
|
||||||
this->InsertApplet(std::move(applet));
|
if (applet->applet_id == AppletId::QLaunch) {
|
||||||
}
|
applet->lifecycle_manager.SetFocusHandlingMode(false);
|
||||||
|
applet->lifecycle_manager.SetOutOfFocusSuspendingEnabled(false);
|
||||||
std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const {
|
m_window_system->TrackApplet(applet, false);
|
||||||
std::scoped_lock lk{m_lock};
|
m_window_system->RequestHomeMenuToGetForeground();
|
||||||
|
} else {
|
||||||
if (const auto it = m_applets.find(aruid); it != m_applets.end()) {
|
m_window_system->TrackApplet(applet, true);
|
||||||
return it->second;
|
m_window_system->RequestApplicationToGetForeground();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
applet->process->Run();
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::Reset() {
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
m_applets.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::RequestExit() {
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
for (const auto& [aruid, applet] : m_applets) {
|
|
||||||
applet->message_queue.RequestExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::RequestResume() {
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
for (const auto& [aruid, applet] : m_applets) {
|
|
||||||
applet->message_queue.RequestResume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::OperationModeChanged() {
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
for (const auto& [aruid, applet] : m_applets) {
|
|
||||||
applet->message_queue.OperationModeChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::FocusStateChanged() {
|
|
||||||
std::scoped_lock lk{m_lock};
|
|
||||||
|
|
||||||
for (const auto& [aruid, applet] : m_applets) {
|
|
||||||
applet->message_queue.FocusStateChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -3,17 +3,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "core/hle/service/am/applet.h"
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
class Process;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
enum class LaunchType {
|
enum class LaunchType {
|
||||||
FrontendInitiated,
|
FrontendInitiated,
|
||||||
ApplicationInitiated,
|
ApplicationInitiated,
|
||||||
@ -33,27 +39,24 @@ public:
|
|||||||
explicit AppletManager(Core::System& system);
|
explicit AppletManager(Core::System& system);
|
||||||
~AppletManager();
|
~AppletManager();
|
||||||
|
|
||||||
void InsertApplet(std::shared_ptr<Applet> applet);
|
void CreateAndInsertByFrontendAppletParameters(std::unique_ptr<Process> process,
|
||||||
void TerminateAndRemoveApplet(AppletResourceUserId aruid);
|
|
||||||
|
|
||||||
void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid,
|
|
||||||
const FrontendAppletParameters& params);
|
const FrontendAppletParameters& params);
|
||||||
std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const;
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
void RequestExit();
|
void RequestExit();
|
||||||
void RequestResume();
|
|
||||||
void OperationModeChanged();
|
void OperationModeChanged();
|
||||||
void FocusStateChanged();
|
|
||||||
|
public:
|
||||||
|
void SetWindowSystem(WindowSystem* window_system);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
|
|
||||||
mutable std::mutex m_lock{};
|
std::mutex m_lock;
|
||||||
std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{};
|
std::condition_variable m_cv;
|
||||||
|
|
||||||
// AudioController state goes here
|
WindowSystem* m_window_system{};
|
||||||
|
|
||||||
|
FrontendAppletParameters m_pending_parameters{};
|
||||||
|
std::unique_ptr<Process> m_pending_process{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
AppletMessageQueue::AppletMessageQueue(Core::System& system)
|
|
||||||
: service_context{system, "AppletMessageQueue"} {
|
|
||||||
on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
|
|
||||||
on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletMessageQueue::~AppletMessageQueue() {
|
|
||||||
service_context.CloseEvent(on_new_message);
|
|
||||||
service_context.CloseEvent(on_operation_mode_changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
|
|
||||||
return on_new_message->GetReadableEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
|
|
||||||
return on_operation_mode_changed->GetReadableEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
|
||||||
{
|
|
||||||
std::scoped_lock lk{lock};
|
|
||||||
messages.push(msg);
|
|
||||||
}
|
|
||||||
on_new_message->Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletMessage AppletMessageQueue::PopMessage() {
|
|
||||||
std::scoped_lock lk{lock};
|
|
||||||
if (messages.empty()) {
|
|
||||||
on_new_message->Clear();
|
|
||||||
return AppletMessage::None;
|
|
||||||
}
|
|
||||||
auto msg = messages.front();
|
|
||||||
messages.pop();
|
|
||||||
if (messages.empty()) {
|
|
||||||
on_new_message->Clear();
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t AppletMessageQueue::GetMessageCount() const {
|
|
||||||
std::scoped_lock lk{lock};
|
|
||||||
return messages.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletMessageQueue::RequestExit() {
|
|
||||||
PushMessage(AppletMessage::Exit);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletMessageQueue::RequestResume() {
|
|
||||||
PushMessage(AppletMessage::Resume);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletMessageQueue::FocusStateChanged() {
|
|
||||||
PushMessage(AppletMessage::FocusStateChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletMessageQueue::OperationModeChanged() {
|
|
||||||
PushMessage(AppletMessage::OperationModeChanged);
|
|
||||||
PushMessage(AppletMessage::PerformanceModeChanged);
|
|
||||||
on_operation_mode_changed->Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
@ -1,43 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include "core/hle/service/am/am_types.h"
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KReadableEvent;
|
|
||||||
} // namespace Kernel
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
class AppletMessageQueue {
|
|
||||||
public:
|
|
||||||
explicit AppletMessageQueue(Core::System& system);
|
|
||||||
~AppletMessageQueue();
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& GetMessageReceiveEvent();
|
|
||||||
Kernel::KReadableEvent& GetOperationModeChangedEvent();
|
|
||||||
void PushMessage(AppletMessage msg);
|
|
||||||
AppletMessage PopMessage();
|
|
||||||
std::size_t GetMessageCount() const;
|
|
||||||
void RequestExit();
|
|
||||||
void RequestResume();
|
|
||||||
void FocusStateChanged();
|
|
||||||
void OperationModeChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
Kernel::KEvent* on_new_message;
|
|
||||||
Kernel::KEvent* on_operation_mode_changed;
|
|
||||||
|
|
||||||
mutable std::mutex lock;
|
|
||||||
std::queue<AppletMessage> messages;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
89
src/core/hle/service/am/button_poller.cpp
Normal file
89
src/core/hle/service/am/button_poller.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/button_poller.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
|
#include "hid_core/frontend/emulated_controller.h"
|
||||||
|
#include "hid_core/hid_core.h"
|
||||||
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
ButtonPressDuration ClassifyPressDuration(std::chrono::steady_clock::time_point start) {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
const auto dur = std::chrono::steady_clock::now() - start;
|
||||||
|
|
||||||
|
// TODO: determine actual thresholds
|
||||||
|
// TODO: these are likely different for each button
|
||||||
|
if (dur < 500ms) {
|
||||||
|
return ButtonPressDuration::ShortPressing;
|
||||||
|
} else if (dur < 1000ms) {
|
||||||
|
return ButtonPressDuration::MiddlePressing;
|
||||||
|
} else {
|
||||||
|
return ButtonPressDuration::LongPressing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system)
|
||||||
|
: m_window_system(window_system) {
|
||||||
|
// TODO: am reads this from the home button state in hid, which is controller-agnostic.
|
||||||
|
Core::HID::ControllerUpdateCallback engine_callback{
|
||||||
|
.on_change =
|
||||||
|
[this](Core::HID::ControllerTriggerType type) {
|
||||||
|
if (type == Core::HID::ControllerTriggerType::Button) {
|
||||||
|
this->OnButtonStateChanged();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.is_npad_service = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
m_handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||||
|
m_handheld_key = m_handheld->SetCallback(engine_callback);
|
||||||
|
m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||||
|
m_player1_key = m_player1->SetCallback(engine_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonPoller::~ButtonPoller() {
|
||||||
|
m_handheld->DeleteCallback(m_handheld_key);
|
||||||
|
m_player1->DeleteCallback(m_player1_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonPoller::OnButtonStateChanged() {
|
||||||
|
const bool home_button =
|
||||||
|
m_handheld->GetHomeButtons().home.Value() || m_player1->GetHomeButtons().home.Value();
|
||||||
|
const bool capture_button = m_handheld->GetCaptureButtons().capture.Value() ||
|
||||||
|
m_player1->GetCaptureButtons().capture.Value();
|
||||||
|
|
||||||
|
// Buttons pressed which were not previously pressed
|
||||||
|
if (home_button && !m_home_button_press_start) {
|
||||||
|
m_home_button_press_start = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
if (capture_button && !m_capture_button_press_start) {
|
||||||
|
m_capture_button_press_start = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
// if (power_button && !m_power_button_press_start) {
|
||||||
|
// m_power_button_press_start = std::chrono::steady_clock::now();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Buttons released which were previously held
|
||||||
|
if (!home_button && m_home_button_press_start) {
|
||||||
|
m_window_system.OnHomeButtonPressed(ClassifyPressDuration(*m_home_button_press_start));
|
||||||
|
m_home_button_press_start = std::nullopt;
|
||||||
|
}
|
||||||
|
if (!capture_button && m_capture_button_press_start) {
|
||||||
|
// TODO
|
||||||
|
m_capture_button_press_start = std::nullopt;
|
||||||
|
}
|
||||||
|
// if (!power_button && m_power_button_press_start) {
|
||||||
|
// // TODO
|
||||||
|
// m_power_button_press_start = std::nullopt;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
43
src/core/hle/service/am/button_poller.h
Normal file
43
src/core/hle/service/am/button_poller.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <optional>
|
||||||
|
#include "hid_core/frontend/emulated_controller.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
namespace HID {
|
||||||
|
class EmulatedController;
|
||||||
|
}
|
||||||
|
|
||||||
|
class System;
|
||||||
|
} // namespace Core
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
|
class ButtonPoller {
|
||||||
|
public:
|
||||||
|
explicit ButtonPoller(Core::System& system, WindowSystem& window_system);
|
||||||
|
~ButtonPoller();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnButtonStateChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WindowSystem& m_window_system;
|
||||||
|
|
||||||
|
Core::HID::EmulatedController* m_handheld{};
|
||||||
|
int m_handheld_key{};
|
||||||
|
Core::HID::EmulatedController* m_player1{};
|
||||||
|
int m_player1_key{};
|
||||||
|
|
||||||
|
std::optional<std::chrono::steady_clock::time_point> m_home_button_press_start{};
|
||||||
|
std::optional<std::chrono::steady_clock::time_point> m_capture_button_press_start{};
|
||||||
|
std::optional<std::chrono::steady_clock::time_point> m_power_button_press_start{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
162
src/core/hle/service/am/event_observer.cpp
Normal file
162
src/core/hle/service/am/event_observer.cpp
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_event.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/event_observer.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
enum class UserDataTag : u32 {
|
||||||
|
WakeupEvent,
|
||||||
|
AppletProcess,
|
||||||
|
};
|
||||||
|
|
||||||
|
EventObserver::EventObserver(Core::System& system, WindowSystem& window_system)
|
||||||
|
: m_system(system), m_context(system, "am:EventObserver"), m_window_system(window_system),
|
||||||
|
m_wakeup_event(m_context), m_wakeup_holder(m_wakeup_event.GetHandle()) {
|
||||||
|
m_window_system.SetEventObserver(this);
|
||||||
|
m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent));
|
||||||
|
m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait));
|
||||||
|
m_thread = std::thread([&] { this->ThreadFunc(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
EventObserver::~EventObserver() {
|
||||||
|
// Signal thread and wait for processing to finish.
|
||||||
|
m_stop_source.request_stop();
|
||||||
|
m_wakeup_event.Signal();
|
||||||
|
m_thread.join();
|
||||||
|
|
||||||
|
// Free remaining owned sessions.
|
||||||
|
auto it = m_process_holder_list.begin();
|
||||||
|
while (it != m_process_holder_list.end()) {
|
||||||
|
// Get the holder.
|
||||||
|
auto* const holder = std::addressof(*it);
|
||||||
|
|
||||||
|
// Remove from the list.
|
||||||
|
it = m_process_holder_list.erase(it);
|
||||||
|
|
||||||
|
// Free the holder.
|
||||||
|
delete holder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::TrackAppletProcess(Applet& applet) {
|
||||||
|
// Don't observe dummy processes.
|
||||||
|
if (!applet.process->IsInitialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate new holder.
|
||||||
|
auto* holder = new ProcessHolder(applet, *applet.process);
|
||||||
|
holder->SetUserData(static_cast<uintptr_t>(UserDataTag::AppletProcess));
|
||||||
|
|
||||||
|
// Insert into list.
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
m_process_holder_list.push_back(*holder);
|
||||||
|
holder->LinkToMultiWait(std::addressof(m_deferred_wait_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal wakeup.
|
||||||
|
m_wakeup_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::RequestUpdate() {
|
||||||
|
m_wakeup_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::LinkDeferred() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
m_multi_wait.MoveAll(std::addressof(m_deferred_wait_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiWaitHolder* EventObserver::WaitSignaled() {
|
||||||
|
while (true) {
|
||||||
|
this->LinkDeferred();
|
||||||
|
|
||||||
|
// If we're done, return before we start waiting.
|
||||||
|
if (m_stop_source.stop_requested()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* selected = m_multi_wait.WaitAny(m_system.Kernel());
|
||||||
|
if (selected != std::addressof(m_wakeup_holder)) {
|
||||||
|
// Unlink the process.
|
||||||
|
selected->UnlinkFromMultiWait();
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::Process(MultiWaitHolder* holder) {
|
||||||
|
switch (static_cast<UserDataTag>(holder->GetUserData())) {
|
||||||
|
case UserDataTag::WakeupEvent:
|
||||||
|
this->OnWakeupEvent(holder);
|
||||||
|
break;
|
||||||
|
case UserDataTag::AppletProcess:
|
||||||
|
this->OnProcessEvent(static_cast<ProcessHolder*>(holder));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::OnWakeupEvent(MultiWaitHolder* holder) {
|
||||||
|
m_wakeup_event.Clear();
|
||||||
|
|
||||||
|
// Perform recalculation.
|
||||||
|
m_window_system.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::OnProcessEvent(ProcessHolder* holder) {
|
||||||
|
// Check process state.
|
||||||
|
auto& applet = holder->GetApplet();
|
||||||
|
auto& process = holder->GetProcess();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_lock, applet.lock};
|
||||||
|
if (process.IsTerminated()) {
|
||||||
|
// Destroy the holder.
|
||||||
|
this->DestroyAppletProcessHolderLocked(holder);
|
||||||
|
} else {
|
||||||
|
// Reset signaled state.
|
||||||
|
process.ResetSignal();
|
||||||
|
|
||||||
|
// Relink wakeup event.
|
||||||
|
holder->LinkToMultiWait(std::addressof(m_deferred_wait_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set running.
|
||||||
|
applet.is_process_running = process.IsRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform recalculation.
|
||||||
|
m_window_system.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) {
|
||||||
|
// Remove from owned list.
|
||||||
|
m_process_holder_list.erase(m_process_holder_list.iterator_to(*holder));
|
||||||
|
|
||||||
|
// Destroy and free.
|
||||||
|
delete holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventObserver::ThreadFunc() {
|
||||||
|
Common::SetCurrentThreadName("am:EventObserver");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
auto* signaled_holder = this->WaitSignaled();
|
||||||
|
if (!signaled_holder) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Process(signaled_holder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
74
src/core/hle/service/am/event_observer.h
Normal file
74
src/core/hle/service/am/event_observer.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/polyfill_thread.h"
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/os/event.h"
|
||||||
|
#include "core/hle/service/os/multi_wait.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class ProcessHolder;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
|
class EventObserver {
|
||||||
|
public:
|
||||||
|
explicit EventObserver(Core::System& system, WindowSystem& window_system);
|
||||||
|
~EventObserver();
|
||||||
|
|
||||||
|
void TrackAppletProcess(Applet& applet);
|
||||||
|
void RequestUpdate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void LinkDeferred();
|
||||||
|
MultiWaitHolder* WaitSignaled();
|
||||||
|
void Process(MultiWaitHolder* holder);
|
||||||
|
bool WaitAndProcessImpl();
|
||||||
|
void LoopProcess();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnWakeupEvent(MultiWaitHolder* holder);
|
||||||
|
void OnProcessEvent(ProcessHolder* holder);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DestroyAppletProcessHolderLocked(ProcessHolder* holder);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ThreadFunc();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// System reference and context.
|
||||||
|
Core::System& m_system;
|
||||||
|
KernelHelpers::ServiceContext m_context;
|
||||||
|
|
||||||
|
// Window manager.
|
||||||
|
WindowSystem& m_window_system;
|
||||||
|
|
||||||
|
// Guest event handle to wake up the event loop processor.
|
||||||
|
Event m_wakeup_event;
|
||||||
|
MultiWaitHolder m_wakeup_holder;
|
||||||
|
|
||||||
|
// Mutex to protect remaining members.
|
||||||
|
std::mutex m_lock{};
|
||||||
|
|
||||||
|
// List of owned process holders.
|
||||||
|
Common::IntrusiveListBaseTraits<ProcessHolder>::ListType m_process_holder_list;
|
||||||
|
|
||||||
|
// Multi-wait objects for new tasks.
|
||||||
|
MultiWait m_multi_wait;
|
||||||
|
MultiWait m_deferred_wait_list;
|
||||||
|
|
||||||
|
// Processing thread.
|
||||||
|
std::thread m_thread{};
|
||||||
|
std::stop_source m_stop_source{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
@ -69,7 +69,11 @@ void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FrontendApplet::Exit() {
|
void FrontendApplet::Exit() {
|
||||||
applet.lock()->caller_applet_broker->SignalCompletion();
|
auto applet_ = applet.lock();
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet_->lock};
|
||||||
|
applet_->is_completed = true;
|
||||||
|
applet_->state_changed_event.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
FrontendAppletSet::FrontendAppletSet() = default;
|
FrontendAppletSet::FrontendAppletSet() = default;
|
||||||
|
@ -3,24 +3,28 @@
|
|||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/service/am/hid_registration.h"
|
#include "core/hle/service/am/hid_registration.h"
|
||||||
#include "core/hle/service/am/process.h"
|
|
||||||
#include "core/hle/service/hid/hid_server.h"
|
#include "core/hle/service/hid/hid_server.h"
|
||||||
|
#include "core/hle/service/os/process.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "hid_core/resource_manager.h"
|
#include "hid_core/resource_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) {
|
HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) {
|
||||||
m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid");
|
m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid", true);
|
||||||
|
|
||||||
if (m_process.IsInitialized()) {
|
if (m_process.IsInitialized()) {
|
||||||
m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
|
m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
|
||||||
true);
|
true);
|
||||||
|
m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HidRegistration::~HidRegistration() {
|
HidRegistration::~HidRegistration() {
|
||||||
if (m_process.IsInitialized()) {
|
if (m_process.IsInitialized()) {
|
||||||
|
m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
|
||||||
|
false);
|
||||||
m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId(
|
m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId(
|
||||||
m_process.GetProcessId());
|
m_process.GetProcessId());
|
||||||
}
|
}
|
||||||
@ -28,6 +32,8 @@ HidRegistration::~HidRegistration() {
|
|||||||
|
|
||||||
void HidRegistration::EnableAppletToGetInput(bool enable) {
|
void HidRegistration::EnableAppletToGetInput(bool enable) {
|
||||||
if (m_process.IsInitialized()) {
|
if (m_process.IsInitialized()) {
|
||||||
|
m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
|
||||||
|
enable);
|
||||||
m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable);
|
m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,11 @@ namespace Service::HID {
|
|||||||
class IHidServer;
|
class IHidServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service {
|
||||||
|
|
||||||
class Process;
|
class Process;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
class HidRegistration {
|
class HidRegistration {
|
||||||
public:
|
public:
|
||||||
|
379
src/core/hle/service/am/lifecycle_manager.cpp
Normal file
379
src/core/hle/service/am/lifecycle_manager.cpp
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "core/hle/service/am/lifecycle_manager.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
LifecycleManager::LifecycleManager(Core::System& system, KernelHelpers::ServiceContext& context,
|
||||||
|
bool is_application)
|
||||||
|
: m_system_event(context), m_operation_mode_changed_system_event(context),
|
||||||
|
m_is_application(is_application) {}
|
||||||
|
|
||||||
|
LifecycleManager::~LifecycleManager() = default;
|
||||||
|
|
||||||
|
Event& LifecycleManager::GetSystemEvent() {
|
||||||
|
return m_system_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event& LifecycleManager::GetOperationModeChangedSystemEvent() {
|
||||||
|
return m_operation_mode_changed_system_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifecycleManager::PushUnorderedMessage(AppletMessage message) {
|
||||||
|
m_unordered_messages.push_back(message);
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletMessage LifecycleManager::PopMessageInOrderOfPriority() {
|
||||||
|
if (m_has_resume) {
|
||||||
|
m_has_resume = false;
|
||||||
|
return AppletMessage::Resume;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_acknowledged_exit != m_has_requested_exit) {
|
||||||
|
m_has_acknowledged_exit = m_has_requested_exit;
|
||||||
|
return AppletMessage::Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_focus_state_changed_notification_enabled) {
|
||||||
|
if (!m_is_application) {
|
||||||
|
if (m_requested_focus_state != m_acknowledged_focus_state) {
|
||||||
|
m_acknowledged_focus_state = m_requested_focus_state;
|
||||||
|
switch (m_requested_focus_state) {
|
||||||
|
case FocusState::InFocus:
|
||||||
|
return AppletMessage::ChangeIntoForeground;
|
||||||
|
case FocusState::NotInFocus:
|
||||||
|
return AppletMessage::ChangeIntoBackground;
|
||||||
|
default:
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (m_has_focus_state_changed) {
|
||||||
|
m_has_focus_state_changed = false;
|
||||||
|
return AppletMessage::FocusStateChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_requested_request_to_prepare_sleep != m_has_acknowledged_request_to_prepare_sleep) {
|
||||||
|
m_has_acknowledged_request_to_prepare_sleep = true;
|
||||||
|
return AppletMessage::RequestToPrepareSleep;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_requested_request_to_display_state != m_acknowledged_request_to_display_state) {
|
||||||
|
m_acknowledged_request_to_display_state = m_requested_request_to_display_state;
|
||||||
|
return AppletMessage::RequestToDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_operation_mode_changed) {
|
||||||
|
m_has_operation_mode_changed = false;
|
||||||
|
return AppletMessage::OperationModeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_performance_mode_changed) {
|
||||||
|
m_has_performance_mode_changed = false;
|
||||||
|
return AppletMessage::PerformanceModeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_sd_card_removed) {
|
||||||
|
m_has_sd_card_removed = false;
|
||||||
|
return AppletMessage::SdCardRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_sleep_required_by_high_temperature) {
|
||||||
|
m_has_sleep_required_by_high_temperature = false;
|
||||||
|
return AppletMessage::SleepRequiredByHighTemperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_sleep_required_by_low_battery) {
|
||||||
|
m_has_sleep_required_by_low_battery = false;
|
||||||
|
return AppletMessage::SleepRequiredByLowBattery;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_auto_power_down) {
|
||||||
|
m_has_auto_power_down = false;
|
||||||
|
return AppletMessage::AutoPowerDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_album_screen_shot_taken) {
|
||||||
|
m_has_album_screen_shot_taken = false;
|
||||||
|
return AppletMessage::AlbumScreenShotTaken;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_has_album_recording_saved) {
|
||||||
|
m_has_album_recording_saved = false;
|
||||||
|
return AppletMessage::AlbumRecordingSaved;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_unordered_messages.empty()) {
|
||||||
|
const auto message = m_unordered_messages.front();
|
||||||
|
m_unordered_messages.pop_front();
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppletMessage::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LifecycleManager::ShouldSignalSystemEvent() {
|
||||||
|
if (m_focus_state_changed_notification_enabled) {
|
||||||
|
if (!m_is_application) {
|
||||||
|
if (m_requested_focus_state != m_acknowledged_focus_state) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (m_has_focus_state_changed) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !m_unordered_messages.empty() || m_has_resume ||
|
||||||
|
(m_has_requested_exit != m_has_acknowledged_exit) ||
|
||||||
|
(m_has_requested_request_to_prepare_sleep !=
|
||||||
|
m_has_acknowledged_request_to_prepare_sleep) ||
|
||||||
|
m_has_operation_mode_changed || m_has_performance_mode_changed ||
|
||||||
|
m_has_sd_card_removed || m_has_sleep_required_by_high_temperature ||
|
||||||
|
m_has_sleep_required_by_low_battery || m_has_auto_power_down ||
|
||||||
|
(m_requested_request_to_display_state != m_acknowledged_request_to_display_state) ||
|
||||||
|
m_has_album_screen_shot_taken || m_has_album_recording_saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifecycleManager::OnOperationAndPerformanceModeChanged() {
|
||||||
|
if (m_operation_mode_changed_notification_enabled) {
|
||||||
|
m_has_operation_mode_changed = true;
|
||||||
|
}
|
||||||
|
if (m_performance_mode_changed_notification_enabled) {
|
||||||
|
m_has_performance_mode_changed = true;
|
||||||
|
}
|
||||||
|
m_operation_mode_changed_system_event.Signal();
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifecycleManager::SignalSystemEventIfNeeded() {
|
||||||
|
// Check our cached value for the system event.
|
||||||
|
const bool applet_message_available = m_applet_message_available;
|
||||||
|
|
||||||
|
// If it's not current, we need to do an update, either clearing or signaling.
|
||||||
|
if (applet_message_available != this->ShouldSignalSystemEvent()) {
|
||||||
|
if (!applet_message_available) {
|
||||||
|
m_system_event.Signal();
|
||||||
|
m_applet_message_available = true;
|
||||||
|
} else {
|
||||||
|
m_system_event.Clear();
|
||||||
|
m_applet_message_available = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LifecycleManager::PopMessage(AppletMessage* out_message) {
|
||||||
|
const auto message = this->PopMessageInOrderOfPriority();
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
|
||||||
|
*out_message = message;
|
||||||
|
return message != AppletMessage::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifecycleManager::SetFocusHandlingMode(bool suspend) {
|
||||||
|
switch (m_focus_handling_mode) {
|
||||||
|
case FocusHandlingMode::AlwaysSuspend:
|
||||||
|
case FocusHandlingMode::SuspendHomeSleep:
|
||||||
|
if (!suspend) {
|
||||||
|
// Disallow suspension.
|
||||||
|
m_focus_handling_mode = FocusHandlingMode::NoSuspend;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FocusHandlingMode::NoSuspend:
|
||||||
|
if (suspend) {
|
||||||
|
// Allow suspension temporally.
|
||||||
|
m_focus_handling_mode = FocusHandlingMode::SuspendHomeSleep;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifecycleManager::SetOutOfFocusSuspendingEnabled(bool enabled) {
|
||||||
|
switch (m_focus_handling_mode) {
|
||||||
|
case FocusHandlingMode::AlwaysSuspend:
|
||||||
|
if (!enabled) {
|
||||||
|
// Allow suspension temporally.
|
||||||
|
m_focus_handling_mode = FocusHandlingMode::SuspendHomeSleep;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FocusHandlingMode::SuspendHomeSleep:
|
||||||
|
case FocusHandlingMode::NoSuspend:
|
||||||
|
if (enabled) {
|
||||||
|
// Allow suspension.
|
||||||
|
m_focus_handling_mode = FocusHandlingMode::AlwaysSuspend;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LifecycleManager::RemoveForceResumeIfPossible() {
|
||||||
|
// If resume is not forced, we have nothing to do.
|
||||||
|
if (m_suspend_mode != SuspendMode::ForceResume) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check activity state.
|
||||||
|
// If we are already resumed, we can remove the forced state.
|
||||||
|
switch (m_activity_state) {
|
||||||
|
case ActivityState::ForegroundVisible:
|
||||||
|
case ActivityState::ForegroundObscured:
|
||||||
|
m_suspend_mode = SuspendMode::NoOverride;
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check focus handling mode.
|
||||||
|
switch (m_focus_handling_mode) {
|
||||||
|
case FocusHandlingMode::AlwaysSuspend:
|
||||||
|
case FocusHandlingMode::SuspendHomeSleep:
|
||||||
|
// If the applet allows suspension, we can remove the forced state.
|
||||||
|
m_suspend_mode = SuspendMode::NoOverride;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FocusHandlingMode::NoSuspend:
|
||||||
|
// If the applet is not an application, we can remove the forced state.
|
||||||
|
// Only applications can be forced to resume.
|
||||||
|
if (!m_is_application) {
|
||||||
|
m_suspend_mode = SuspendMode::NoOverride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LifecycleManager::IsRunnable() const {
|
||||||
|
// If suspend is forced, return that.
|
||||||
|
if (m_forced_suspend) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check suspend mode override.
|
||||||
|
switch (m_suspend_mode) {
|
||||||
|
case SuspendMode::NoOverride:
|
||||||
|
// Continue processing.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SuspendMode::ForceResume:
|
||||||
|
// The applet is runnable during forced resumption when its exit is requested.
|
||||||
|
return m_has_requested_exit;
|
||||||
|
|
||||||
|
case SuspendMode::ForceSuspend:
|
||||||
|
// The applet is never runnable during forced suspension.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always run if exit is requested.
|
||||||
|
if (m_has_requested_exit) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_activity_state == ActivityState::ForegroundVisible) {
|
||||||
|
// The applet is runnable now.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_activity_state == ActivityState::ForegroundObscured) {
|
||||||
|
switch (m_focus_handling_mode) {
|
||||||
|
case FocusHandlingMode::AlwaysSuspend:
|
||||||
|
// The applet is not runnable while running the applet.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case FocusHandlingMode::SuspendHomeSleep:
|
||||||
|
// The applet is runnable while running the applet.
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case FocusHandlingMode::NoSuspend:
|
||||||
|
// The applet is always runnable.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The activity is a suspended one.
|
||||||
|
// The applet should be suspended unless it has disabled suspension.
|
||||||
|
return m_focus_handling_mode == FocusHandlingMode::NoSuspend;
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusState LifecycleManager::GetFocusStateWhileForegroundObscured() const {
|
||||||
|
switch (m_focus_handling_mode) {
|
||||||
|
case FocusHandlingMode::AlwaysSuspend:
|
||||||
|
// The applet never learns it has lost focus.
|
||||||
|
return FocusState::InFocus;
|
||||||
|
|
||||||
|
case FocusHandlingMode::SuspendHomeSleep:
|
||||||
|
// The applet learns it has lost focus when launching a child applet.
|
||||||
|
return FocusState::NotInFocus;
|
||||||
|
|
||||||
|
case FocusHandlingMode::NoSuspend:
|
||||||
|
// The applet always learns it has lost focus.
|
||||||
|
return FocusState::NotInFocus;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusState LifecycleManager::GetFocusStateWhileBackground(bool is_obscured) const {
|
||||||
|
switch (m_focus_handling_mode) {
|
||||||
|
case FocusHandlingMode::AlwaysSuspend:
|
||||||
|
// The applet never learns it has lost focus.
|
||||||
|
return FocusState::InFocus;
|
||||||
|
|
||||||
|
case FocusHandlingMode::SuspendHomeSleep:
|
||||||
|
// The applet learns it has lost focus when launching a child applet.
|
||||||
|
return is_obscured ? FocusState::NotInFocus : FocusState::InFocus;
|
||||||
|
|
||||||
|
case FocusHandlingMode::NoSuspend:
|
||||||
|
// The applet always learns it has lost focus.
|
||||||
|
return m_is_application ? FocusState::Background : FocusState::NotInFocus;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LifecycleManager::UpdateRequestedFocusState() {
|
||||||
|
FocusState new_state{};
|
||||||
|
|
||||||
|
if (m_suspend_mode == SuspendMode::NoOverride) {
|
||||||
|
// With no forced suspend or resume, we take the focus state designated
|
||||||
|
// by the combination of the activity flag and the focus handling mode.
|
||||||
|
switch (m_activity_state) {
|
||||||
|
case ActivityState::ForegroundVisible:
|
||||||
|
new_state = FocusState::InFocus;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActivityState::ForegroundObscured:
|
||||||
|
new_state = this->GetFocusStateWhileForegroundObscured();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActivityState::BackgroundVisible:
|
||||||
|
new_state = this->GetFocusStateWhileBackground(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActivityState::BackgroundObscured:
|
||||||
|
new_state = this->GetFocusStateWhileBackground(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// With forced suspend or resume, the applet is guaranteed to be background.
|
||||||
|
new_state = this->GetFocusStateWhileBackground(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_state != m_requested_focus_state) {
|
||||||
|
// Mark the focus state as ready for update.
|
||||||
|
m_requested_focus_state = new_state;
|
||||||
|
|
||||||
|
// We changed the focus state.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We didn't change the focus state.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
183
src/core/hle/service/am/lifecycle_manager.h
Normal file
183
src/core/hle/service/am/lifecycle_manager.h
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/os/event.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
enum class ActivityState : u32 {
|
||||||
|
ForegroundVisible = 0,
|
||||||
|
ForegroundObscured = 1,
|
||||||
|
BackgroundVisible = 2,
|
||||||
|
BackgroundObscured = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FocusHandlingMode : u32 {
|
||||||
|
AlwaysSuspend = 0,
|
||||||
|
SuspendHomeSleep = 1,
|
||||||
|
NoSuspend = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SuspendMode : u32 {
|
||||||
|
NoOverride = 0,
|
||||||
|
ForceResume = 1,
|
||||||
|
ForceSuspend = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
class LifecycleManager {
|
||||||
|
public:
|
||||||
|
explicit LifecycleManager(Core::System& system, KernelHelpers::ServiceContext& context,
|
||||||
|
bool is_application);
|
||||||
|
~LifecycleManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Event& GetSystemEvent();
|
||||||
|
Event& GetOperationModeChangedSystemEvent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool IsApplication() {
|
||||||
|
return m_is_application;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetForcedSuspend() {
|
||||||
|
return m_forced_suspend;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetExitRequested() {
|
||||||
|
return m_has_requested_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityState GetActivityState() {
|
||||||
|
return m_activity_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusState GetAndClearFocusState() {
|
||||||
|
m_acknowledged_focus_state = m_requested_focus_state;
|
||||||
|
return m_acknowledged_focus_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFocusState(FocusState state) {
|
||||||
|
if (m_requested_focus_state != state) {
|
||||||
|
m_has_focus_state_changed = true;
|
||||||
|
}
|
||||||
|
m_requested_focus_state = state;
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestExit() {
|
||||||
|
m_has_requested_exit = true;
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestResumeNotification() {
|
||||||
|
// NOTE: this appears to be a bug in am.
|
||||||
|
// If an applet makes a concurrent request to receive resume notifications
|
||||||
|
// while it is being suspended, the first resume notification will be lost.
|
||||||
|
// This is not the case with other notification types.
|
||||||
|
if (m_resume_notification_enabled) {
|
||||||
|
m_has_resume = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnOperationAndPerformanceModeChanged();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetFocusStateChangedNotificationEnabled(bool enabled) {
|
||||||
|
m_focus_state_changed_notification_enabled = enabled;
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetOperationModeChangedNotificationEnabled(bool enabled) {
|
||||||
|
m_operation_mode_changed_notification_enabled = enabled;
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPerformanceModeChangedNotificationEnabled(bool enabled) {
|
||||||
|
m_performance_mode_changed_notification_enabled = enabled;
|
||||||
|
this->SignalSystemEventIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetResumeNotificationEnabled(bool enabled) {
|
||||||
|
m_resume_notification_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetActivityState(ActivityState state) {
|
||||||
|
m_activity_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSuspendMode(SuspendMode mode) {
|
||||||
|
m_suspend_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetForcedSuspend(bool enabled) {
|
||||||
|
m_forced_suspend = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetFocusHandlingMode(bool suspend);
|
||||||
|
void SetOutOfFocusSuspendingEnabled(bool enabled);
|
||||||
|
void RemoveForceResumeIfPossible();
|
||||||
|
bool IsRunnable() const;
|
||||||
|
bool UpdateRequestedFocusState();
|
||||||
|
void SignalSystemEventIfNeeded();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void PushUnorderedMessage(AppletMessage message);
|
||||||
|
bool PopMessage(AppletMessage* out_message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FocusState GetFocusStateWhileForegroundObscured() const;
|
||||||
|
FocusState GetFocusStateWhileBackground(bool is_obscured) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppletMessage PopMessageInOrderOfPriority();
|
||||||
|
bool ShouldSignalSystemEvent();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Event m_system_event;
|
||||||
|
Event m_operation_mode_changed_system_event;
|
||||||
|
|
||||||
|
std::list<AppletMessage> m_unordered_messages{};
|
||||||
|
|
||||||
|
bool m_is_application{};
|
||||||
|
bool m_focus_state_changed_notification_enabled{true};
|
||||||
|
bool m_operation_mode_changed_notification_enabled{true};
|
||||||
|
bool m_performance_mode_changed_notification_enabled{true};
|
||||||
|
bool m_resume_notification_enabled{};
|
||||||
|
|
||||||
|
bool m_requested_request_to_display_state{};
|
||||||
|
bool m_acknowledged_request_to_display_state{};
|
||||||
|
bool m_has_resume{};
|
||||||
|
bool m_has_focus_state_changed{true};
|
||||||
|
bool m_has_album_recording_saved{};
|
||||||
|
bool m_has_album_screen_shot_taken{};
|
||||||
|
bool m_has_auto_power_down{};
|
||||||
|
bool m_has_sleep_required_by_low_battery{};
|
||||||
|
bool m_has_sleep_required_by_high_temperature{};
|
||||||
|
bool m_has_sd_card_removed{};
|
||||||
|
bool m_has_performance_mode_changed{};
|
||||||
|
bool m_has_operation_mode_changed{};
|
||||||
|
bool m_has_requested_request_to_prepare_sleep{};
|
||||||
|
bool m_has_acknowledged_request_to_prepare_sleep{};
|
||||||
|
bool m_has_requested_exit{};
|
||||||
|
bool m_has_acknowledged_exit{};
|
||||||
|
bool m_applet_message_available{};
|
||||||
|
|
||||||
|
bool m_forced_suspend{};
|
||||||
|
FocusHandlingMode m_focus_handling_mode{FocusHandlingMode::SuspendHomeSleep};
|
||||||
|
ActivityState m_activity_state{ActivityState::ForegroundVisible};
|
||||||
|
SuspendMode m_suspend_mode{SuspendMode::NoOverride};
|
||||||
|
FocusState m_requested_focus_state{};
|
||||||
|
FocusState m_acknowledged_focus_state{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
130
src/core/hle/service/am/process_creation.cpp
Normal file
130
src/core/hle/service/am/process_creation.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/file_sys/content_archive.h"
|
||||||
|
#include "core/file_sys/nca_metadata.h"
|
||||||
|
#include "core/file_sys/patch_manager.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
|
#include "core/file_sys/romfs_factory.h"
|
||||||
|
#include "core/hle/service/am/process_creation.h"
|
||||||
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
|
#include "core/hle/service/os/process.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||||
|
std::optional<FileSys::ContentProviderUnionSlot> slot) {
|
||||||
|
if (!slot.has_value()) {
|
||||||
|
return FileSys::StorageId::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*slot) {
|
||||||
|
case FileSys::ContentProviderUnionSlot::UserNAND:
|
||||||
|
return FileSys::StorageId::NandUser;
|
||||||
|
case FileSys::ContentProviderUnionSlot::SysNAND:
|
||||||
|
return FileSys::StorageId::NandSystem;
|
||||||
|
case FileSys::ContentProviderUnionSlot::SDMC:
|
||||||
|
return FileSys::StorageId::SdCard;
|
||||||
|
case FileSys::ContentProviderUnionSlot::FrontendManual:
|
||||||
|
return FileSys::StorageId::Host;
|
||||||
|
default:
|
||||||
|
return FileSys::StorageId::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Process> CreateProcessImpl(std::unique_ptr<Loader::AppLoader>& out_loader,
|
||||||
|
Loader::ResultStatus& out_load_result,
|
||||||
|
Core::System& system, FileSys::VirtualFile file,
|
||||||
|
u64 program_id, u64 program_index) {
|
||||||
|
// Get the appropriate loader to parse this NCA.
|
||||||
|
out_loader = Loader::GetLoader(system, file, program_id, program_index);
|
||||||
|
|
||||||
|
// Ensure we have a loader which can parse the NCA.
|
||||||
|
if (!out_loader) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to load the process.
|
||||||
|
auto process = std::make_unique<Process>(system);
|
||||||
|
if (process->Initialize(*out_loader, out_load_result)) {
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id,
|
||||||
|
u8 minimum_key_generation, u8 maximum_key_generation) {
|
||||||
|
// Attempt to load program NCA.
|
||||||
|
FileSys::VirtualFile nca_raw{};
|
||||||
|
|
||||||
|
// Get the program NCA from storage.
|
||||||
|
auto& storage = system.GetContentProviderUnion();
|
||||||
|
nca_raw = storage.GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
|
||||||
|
|
||||||
|
// Ensure we retrieved a program NCA.
|
||||||
|
if (!nca_raw) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we have a suitable version.
|
||||||
|
if (minimum_key_generation > 0) {
|
||||||
|
FileSys::NCA nca(nca_raw);
|
||||||
|
if (nca.GetStatus() == Loader::ResultStatus::Success &&
|
||||||
|
(nca.GetKeyGeneration() < minimum_key_generation ||
|
||||||
|
nca.GetKeyGeneration() > maximum_key_generation)) {
|
||||||
|
LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id,
|
||||||
|
nca.GetKeyGeneration());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Loader::AppLoader> loader;
|
||||||
|
Loader::ResultStatus status;
|
||||||
|
return CreateProcessImpl(loader, status, system, nca_raw, program_id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control,
|
||||||
|
std::unique_ptr<Loader::AppLoader>& out_loader,
|
||||||
|
Loader::ResultStatus& out_load_result,
|
||||||
|
Core::System& system, FileSys::VirtualFile file,
|
||||||
|
u64 program_id, u64 program_index) {
|
||||||
|
auto process =
|
||||||
|
CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index);
|
||||||
|
if (!process) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSys::NACP nacp;
|
||||||
|
if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
|
||||||
|
out_control = nacp.GetRawBytes();
|
||||||
|
} else {
|
||||||
|
out_control.resize(sizeof(FileSys::RawNACP));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& storage = system.GetContentProviderUnion();
|
||||||
|
Service::Glue::ApplicationLaunchProperty launch{};
|
||||||
|
launch.title_id = process->GetProgramId();
|
||||||
|
|
||||||
|
FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage};
|
||||||
|
launch.version = pm.GetGameVersion().value_or(0);
|
||||||
|
|
||||||
|
// TODO(DarkLordZach): When FSController/Game Card Support is added, if
|
||||||
|
// current_process_game_card use correct StorageId
|
||||||
|
launch.base_game_storage_id = GetStorageIdForFrontendSlot(
|
||||||
|
storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program));
|
||||||
|
launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(
|
||||||
|
FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program));
|
||||||
|
|
||||||
|
system.GetARPManager().Register(launch.title_id, launch, out_control);
|
||||||
|
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
35
src/core/hle/service/am/process_creation.h
Normal file
35
src/core/hle/service/am/process_creation.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/file_sys/vfs/vfs_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Loader {
|
||||||
|
class AppLoader;
|
||||||
|
enum class ResultStatus : u16;
|
||||||
|
} // namespace Loader
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
class Process;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
std::unique_ptr<Process> CreateProcess(Core::System& system, u64 program_id,
|
||||||
|
u8 minimum_key_generation, u8 maximum_key_generation);
|
||||||
|
std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control,
|
||||||
|
std::unique_ptr<Loader::AppLoader>& out_loader,
|
||||||
|
Loader::ResultStatus& out_load_result,
|
||||||
|
Core::System& system, FileSys::VirtualFile file,
|
||||||
|
u64 program_id, u64 program_index);
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
15
src/core/hle/service/am/process_holder.cpp
Normal file
15
src/core/hle/service/am/process_holder.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/kernel/k_process.h"
|
||||||
|
#include "core/hle/service/am/process_holder.h"
|
||||||
|
#include "core/hle/service/os/process.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ProcessHolder::ProcessHolder(Applet& applet, Process& process)
|
||||||
|
: MultiWaitHolder(process.GetHandle()), m_applet(applet), m_process(process) {}
|
||||||
|
|
||||||
|
ProcessHolder::~ProcessHolder() = default;
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
34
src/core/hle/service/am/process_holder.h
Normal file
34
src/core/hle/service/am/process_holder.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/os/multi_wait_holder.h"
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
class Process;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ProcessHolder : public MultiWaitHolder, public Common::IntrusiveListBaseNode<ProcessHolder> {
|
||||||
|
public:
|
||||||
|
explicit ProcessHolder(Applet& applet, Process& process);
|
||||||
|
~ProcessHolder();
|
||||||
|
|
||||||
|
Applet& GetApplet() const {
|
||||||
|
return m_applet;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process& GetProcess() const {
|
||||||
|
return m_process;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Applet& m_applet;
|
||||||
|
Process& m_process;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
@ -6,12 +6,14 @@
|
|||||||
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
||||||
#include "core/hle/service/am/service/library_applet_proxy.h"
|
#include "core/hle/service/am/service/library_applet_proxy.h"
|
||||||
#include "core/hle/service/am/service/system_applet_proxy.h"
|
#include "core/hle/service/am/service/system_applet_proxy.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_)
|
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
|
||||||
: ServiceFramework{system_, "appletAE"} {
|
WindowSystem& window_system)
|
||||||
|
: ServiceFramework{system_, "appletAE"}, m_window_system{window_system} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
|
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
|
||||||
@ -36,8 +38,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
|
|||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||||
*out_system_applet_proxy =
|
*out_system_applet_proxy = std::make_shared<ISystemAppletProxy>(
|
||||||
std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get());
|
system, applet, process_handle.Get(), m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
} else {
|
} else {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
@ -52,8 +54,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
|
|||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||||
*out_library_applet_proxy =
|
*out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>(
|
||||||
std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get());
|
system, applet, process_handle.Get(), m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
} else {
|
} else {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
@ -73,7 +75,7 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
|
|||||||
|
|
||||||
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
|
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
|
||||||
ProcessId process_id) {
|
ProcessId process_id) {
|
||||||
return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
|
return m_window_system.GetByAppletResourceUserId(process_id.pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -14,11 +14,12 @@ struct Applet;
|
|||||||
struct AppletAttribute;
|
struct AppletAttribute;
|
||||||
class ILibraryAppletProxy;
|
class ILibraryAppletProxy;
|
||||||
class ISystemAppletProxy;
|
class ISystemAppletProxy;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class IAllSystemAppletProxiesService final
|
class IAllSystemAppletProxiesService final
|
||||||
: public ServiceFramework<IAllSystemAppletProxiesService> {
|
: public ServiceFramework<IAllSystemAppletProxiesService> {
|
||||||
public:
|
public:
|
||||||
explicit IAllSystemAppletProxiesService(Core::System& system_);
|
explicit IAllSystemAppletProxiesService(Core::System& system_, WindowSystem& window_system);
|
||||||
~IAllSystemAppletProxiesService() override;
|
~IAllSystemAppletProxiesService() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -35,6 +36,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AM
|
} // namespace AM
|
||||||
|
@ -19,7 +19,7 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
|||||||
{21, nullptr, "TryPopFromAppletBoundChannel"},
|
{21, nullptr, "TryPopFromAppletBoundChannel"},
|
||||||
{40, nullptr, "GetDisplayLogicalResolution"},
|
{40, nullptr, "GetDisplayLogicalResolution"},
|
||||||
{42, nullptr, "SetDisplayMagnification"},
|
{42, nullptr, "SetDisplayMagnification"},
|
||||||
{50, nullptr, "SetHomeButtonDoubleClickEnabled"},
|
{50, D<&IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled>, "SetHomeButtonDoubleClickEnabled"},
|
||||||
{51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
|
{51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
|
||||||
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
||||||
{60, nullptr, "IsVrModeCurtainRequired"},
|
{60, nullptr, "IsVrModeCurtainRequired"},
|
||||||
@ -40,6 +40,13 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
|||||||
|
|
||||||
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
||||||
|
|
||||||
|
Result IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled(
|
||||||
|
bool home_button_double_click_enabled) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, home_button_double_click_enabled={}",
|
||||||
|
home_button_double_click_enabled);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled(
|
Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled(
|
||||||
Out<bool> out_home_button_double_click_enabled) {
|
Out<bool> out_home_button_double_click_enabled) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
@ -16,6 +16,7 @@ public:
|
|||||||
~IAppletCommonFunctions() override;
|
~IAppletCommonFunctions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Result SetHomeButtonDoubleClickEnabled(bool home_button_double_click_enabled);
|
||||||
Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
|
Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
|
||||||
Result SetCpuBoostRequestPriority(s32 priority);
|
Result SetCpuBoostRequestPriority(s32 priority);
|
||||||
Result GetCurrentApplicationId(Out<u64> out_application_id);
|
Result GetCurrentApplicationId(Out<u64> out_application_id);
|
||||||
|
@ -9,12 +9,16 @@
|
|||||||
#include "core/hle/service/am/service/application_accessor.h"
|
#include "core/hle/service/am/service/application_accessor.h"
|
||||||
#include "core/hle/service/am/service/library_applet_accessor.h"
|
#include "core/hle/service/am/service/library_applet_accessor.h"
|
||||||
#include "core/hle/service/am/service/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet)
|
IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
: ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) {
|
WindowSystem& window_system)
|
||||||
|
: ServiceFramework{system_, "IApplicationAccessor"}, m_window_system(window_system),
|
||||||
|
m_applet(std::move(applet)) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
|
{0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
|
||||||
@ -59,7 +63,15 @@ Result IApplicationAccessor::Start() {
|
|||||||
|
|
||||||
Result IApplicationAccessor::RequestExit() {
|
Result IApplicationAccessor::RequestExit() {
|
||||||
LOG_INFO(Service_AM, "called");
|
LOG_INFO(Service_AM, "called");
|
||||||
m_applet->message_queue.RequestExit();
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
if (m_applet->exit_locked) {
|
||||||
|
m_applet->lifecycle_manager.RequestExit();
|
||||||
|
m_applet->UpdateSuspensionStateLocked(true);
|
||||||
|
} else {
|
||||||
|
m_applet->process->Terminate();
|
||||||
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,13 +83,14 @@ Result IApplicationAccessor::Terminate() {
|
|||||||
|
|
||||||
Result IApplicationAccessor::GetResult() {
|
Result IApplicationAccessor::GetResult() {
|
||||||
LOG_INFO(Service_AM, "called");
|
LOG_INFO(Service_AM, "called");
|
||||||
R_SUCCEED();
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
R_RETURN(m_applet->terminate_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationAccessor::GetAppletStateChangedEvent(
|
Result IApplicationAccessor::GetAppletStateChangedEvent(
|
||||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
LOG_INFO(Service_AM, "called");
|
LOG_INFO(Service_AM, "called");
|
||||||
*out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle();
|
*out_event = m_applet->state_changed_event.GetHandle();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +109,15 @@ Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind,
|
|||||||
|
|
||||||
Result IApplicationAccessor::GetApplicationControlProperty(
|
Result IApplicationAccessor::GetApplicationControlProperty(
|
||||||
OutBuffer<BufferAttr_HipcMapAlias> out_control_property) {
|
OutBuffer<BufferAttr_HipcMapAlias> out_control_property) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
R_THROW(ResultUnknown);
|
|
||||||
|
std::vector<u8> nacp;
|
||||||
|
R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id));
|
||||||
|
|
||||||
|
std::memcpy(out_control_property.data(), nacp.data(),
|
||||||
|
std::min(out_control_property.size(), nacp.size()));
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationAccessor::SetUsers(bool enable,
|
Result IApplicationAccessor::SetUsers(bool enable,
|
||||||
@ -114,8 +134,9 @@ Result IApplicationAccessor::GetCurrentLibraryApplet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationAccessor::RequestForApplicationToGetForeground() {
|
Result IApplicationAccessor::RequestForApplicationToGetForeground() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
R_THROW(ResultUnknown);
|
m_window_system.RequestApplicationToGetForeground();
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) {
|
Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) {
|
||||||
|
@ -13,10 +13,12 @@ namespace Service::AM {
|
|||||||
struct Applet;
|
struct Applet;
|
||||||
class ILibraryAppletAccessor;
|
class ILibraryAppletAccessor;
|
||||||
class IStorage;
|
class IStorage;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> {
|
class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
|
explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
WindowSystem& window_system);
|
||||||
~IApplicationAccessor() override;
|
~IApplicationAccessor() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -34,6 +36,7 @@ private:
|
|||||||
Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
|
Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
|
||||||
Result ReportApplicationExitTimeout();
|
Result ReportApplicationExitTimeout();
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,17 +1,57 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/file_sys/nca_metadata.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
#include "core/hle/service/am/am_types.h"
|
#include "core/hle/service/am/am_types.h"
|
||||||
#include "core/hle/service/am/applet.h"
|
#include "core/hle/service/am/applet.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/process_creation.h"
|
||||||
#include "core/hle/service/am/service/application_accessor.h"
|
#include "core/hle/service/am/service/application_accessor.h"
|
||||||
#include "core/hle/service/am/service/application_creator.h"
|
#include "core/hle/service/am/service/application_creator.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IApplicationCreator::IApplicationCreator(Core::System& system_)
|
namespace {
|
||||||
: ServiceFramework{system_, "IApplicationCreator"} {
|
|
||||||
|
Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_application_accessor,
|
||||||
|
Core::System& system, WindowSystem& window_system, u64 program_id) {
|
||||||
|
FileSys::VirtualFile nca_raw{};
|
||||||
|
|
||||||
|
// Get the program NCA from storage.
|
||||||
|
auto& storage = system.GetContentProviderUnion();
|
||||||
|
nca_raw = storage.GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
|
||||||
|
|
||||||
|
// Ensure we retrieved a program NCA.
|
||||||
|
R_UNLESS(nca_raw != nullptr, ResultUnknown);
|
||||||
|
|
||||||
|
std::vector<u8> control;
|
||||||
|
std::unique_ptr<Loader::AppLoader> loader;
|
||||||
|
Loader::ResultStatus result;
|
||||||
|
auto process =
|
||||||
|
CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0);
|
||||||
|
R_UNLESS(process != nullptr, ResultUnknown);
|
||||||
|
|
||||||
|
const auto applet = std::make_shared<Applet>(system, std::move(process), true);
|
||||||
|
applet->program_id = program_id;
|
||||||
|
applet->applet_id = AppletId::Application;
|
||||||
|
applet->type = AppletType::Application;
|
||||||
|
applet->library_applet_mode = LibraryAppletMode::AllForeground;
|
||||||
|
|
||||||
|
window_system.TrackApplet(applet, true);
|
||||||
|
|
||||||
|
*out_application_accessor =
|
||||||
|
std::make_shared<IApplicationAccessor>(system, applet, window_system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
IApplicationCreator::IApplicationCreator(Core::System& system_, WindowSystem& window_system)
|
||||||
|
: ServiceFramework{system_, "IApplicationCreator"}, m_window_system{window_system} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
|
{0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
|
||||||
@ -28,8 +68,9 @@ IApplicationCreator::~IApplicationCreator() = default;
|
|||||||
|
|
||||||
Result IApplicationCreator::CreateApplication(
|
Result IApplicationCreator::CreateApplication(
|
||||||
Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) {
|
Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) {
|
||||||
LOG_ERROR(Service_NS, "called, application_id={:x}", application_id);
|
LOG_INFO(Service_NS, "called, application_id={:016X}", application_id);
|
||||||
R_THROW(ResultUnknown);
|
R_RETURN(
|
||||||
|
CreateGuestApplication(out_application_accessor, system, m_window_system, application_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -10,14 +10,17 @@ namespace Service::AM {
|
|||||||
|
|
||||||
class IApplicationAccessor;
|
class IApplicationAccessor;
|
||||||
struct Applet;
|
struct Applet;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationCreator(Core::System& system_);
|
explicit IApplicationCreator(Core::System& system_, WindowSystem& window_system);
|
||||||
~IApplicationCreator() override;
|
~IApplicationCreator() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
|
Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -123,13 +123,13 @@ Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID use
|
|||||||
LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
|
LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
|
||||||
|
|
||||||
FileSys::SaveDataAttribute attribute{};
|
FileSys::SaveDataAttribute attribute{};
|
||||||
attribute.title_id = m_applet->program_id;
|
attribute.program_id = m_applet->program_id;
|
||||||
attribute.user_id = user_id.AsU128();
|
attribute.user_id = user_id.AsU128();
|
||||||
attribute.type = FileSys::SaveDataType::SaveData;
|
attribute.type = FileSys::SaveDataType::Account;
|
||||||
|
|
||||||
FileSys::VirtualDir save_data{};
|
FileSys::VirtualDir save_data{};
|
||||||
R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
|
R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
|
||||||
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute));
|
&save_data, FileSys::SaveDataSpaceId::User, attribute));
|
||||||
|
|
||||||
*out_size = 0;
|
*out_size = 0;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -181,7 +181,8 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
|
Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
|
||||||
LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(),
|
LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({:04}-{:04})",
|
||||||
|
terminate_result.GetInnerValue(),
|
||||||
static_cast<u32>(terminate_result.GetModule()) + 2000,
|
static_cast<u32>(terminate_result.GetModule()) + 2000,
|
||||||
terminate_result.GetDescription());
|
terminate_result.GetDescription());
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process)
|
Kernel::KProcess* process, WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{
|
: ServiceFramework{system_, "IApplicationProxy"},
|
||||||
std::move(applet)} {
|
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
@ -70,7 +70,7 @@ Result IApplicationProxy::GetDebugFunctions(
|
|||||||
Result IApplicationProxy::GetWindowController(
|
Result IApplicationProxy::GetWindowController(
|
||||||
Out<SharedPointer<IWindowController>> out_window_controller) {
|
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_window_controller = std::make_shared<IWindowController>(system, m_applet);
|
*out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,8 @@ Result IApplicationProxy::GetCommonStateGetter(
|
|||||||
Result IApplicationProxy::GetLibraryAppletCreator(
|
Result IApplicationProxy::GetLibraryAppletCreator(
|
||||||
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
|
*out_library_applet_creator =
|
||||||
|
std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +18,12 @@ class ILibraryAppletCreator;
|
|||||||
class IProcessWindingController;
|
class IProcessWindingController;
|
||||||
class ISelfController;
|
class ISelfController;
|
||||||
class IWindowController;
|
class IWindowController;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process);
|
Kernel::KProcess* process, WindowSystem& window_system);
|
||||||
~IApplicationProxy();
|
~IApplicationProxy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -40,6 +41,7 @@ private:
|
|||||||
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
|
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WindowSystem& m_window_system;
|
||||||
Kernel::KProcess* const m_process;
|
Kernel::KProcess* const m_process;
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
@ -6,12 +6,14 @@
|
|||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/service/application_proxy.h"
|
#include "core/hle/service/am/service/application_proxy.h"
|
||||||
#include "core/hle/service/am/service/application_proxy_service.h"
|
#include "core/hle/service/am/service/application_proxy_service.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IApplicationProxyService::IApplicationProxyService(Core::System& system_)
|
IApplicationProxyService::IApplicationProxyService(Core::System& system_,
|
||||||
: ServiceFramework{system_, "appletOE"} {
|
WindowSystem& window_system)
|
||||||
|
: ServiceFramework{system_, "appletOE"}, m_window_system{window_system} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
|
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
|
||||||
};
|
};
|
||||||
@ -26,8 +28,8 @@ Result IApplicationProxyService::OpenApplicationProxy(
|
|||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
if (const auto applet = this->GetAppletFromProcessId(pid)) {
|
if (const auto applet = this->GetAppletFromProcessId(pid)) {
|
||||||
*out_application_proxy =
|
*out_application_proxy = std::make_shared<IApplicationProxy>(
|
||||||
std::make_shared<IApplicationProxy>(system, applet, process_handle.Get());
|
system, applet, process_handle.Get(), m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
} else {
|
} else {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
@ -36,7 +38,7 @@ Result IApplicationProxyService::OpenApplicationProxy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) {
|
std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) {
|
||||||
return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
|
return m_window_system.GetByAppletResourceUserId(process_id.pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
@ -12,10 +12,11 @@ namespace AM {
|
|||||||
|
|
||||||
struct Applet;
|
struct Applet;
|
||||||
class IApplicationProxy;
|
class IApplicationProxy;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
|
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationProxyService(Core::System& system_);
|
explicit IApplicationProxyService(Core::System& system_, WindowSystem& window_system);
|
||||||
~IApplicationProxyService() override;
|
~IApplicationProxyService() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -24,6 +25,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AM
|
} // namespace AM
|
||||||
|
@ -80,15 +80,14 @@ ICommonStateGetter::~ICommonStateGetter() = default;
|
|||||||
|
|
||||||
Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_event = &m_applet->message_queue.GetMessageReceiveEvent();
|
*out_event = m_applet->lifecycle_manager.GetSystemEvent().GetHandle();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) {
|
Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
*out_applet_message = m_applet->message_queue.PopMessage();
|
if (!m_applet->lifecycle_manager.PopMessage(out_applet_message)) {
|
||||||
if (*out_applet_message == AppletMessage::None) {
|
|
||||||
LOG_ERROR(Service_AM, "Tried to pop message but none was available!");
|
LOG_ERROR(Service_AM, "Tried to pop message but none was available!");
|
||||||
R_THROW(AM::ResultNoMessages);
|
R_THROW(AM::ResultNoMessages);
|
||||||
}
|
}
|
||||||
@ -100,7 +99,7 @@ Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state)
|
|||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
std::scoped_lock lk{m_applet->lock};
|
||||||
*out_focus_state = m_applet->focus_state;
|
*out_focus_state = m_applet->lifecycle_manager.GetAndClearFocusState();
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@ -137,7 +136,7 @@ Result ICommonStateGetter::GetWriterLockAccessorEx(
|
|||||||
Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(
|
Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(
|
||||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_event = &m_applet->message_queue.GetOperationModeChangedEvent();
|
*out_event = m_applet->lifecycle_manager.GetOperationModeChangedSystemEvent().GetHandle();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,9 +259,9 @@ Result ICommonStateGetter::GetAppletLaunchedHistory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ICommonStateGetter::GetSettingsPlatformRegion(
|
Result ICommonStateGetter::GetSettingsPlatformRegion(
|
||||||
Out<SysPlatformRegion> out_settings_platform_region) {
|
Out<Set::PlatformRegion> out_settings_platform_region) {
|
||||||
LOG_INFO(Service_AM, "called");
|
LOG_INFO(Service_AM, "called");
|
||||||
*out_settings_platform_region = SysPlatformRegion::Global;
|
*out_settings_platform_region = Set::PlatformRegion::Global;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "core/hle/service/cmif_types.h"
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/pm/pm.h"
|
#include "core/hle/service/pm/pm.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
#include "core/hle/service/set/settings_types.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
class KReadableEvent;
|
class KReadableEvent;
|
||||||
@ -50,7 +51,7 @@ private:
|
|||||||
Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
|
Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
|
||||||
Result GetAppletLaunchedHistory(Out<s32> out_count,
|
Result GetAppletLaunchedHistory(Out<s32> out_count,
|
||||||
OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
|
OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
|
||||||
Result GetSettingsPlatformRegion(Out<SysPlatformRegion> out_settings_platform_region);
|
Result GetSettingsPlatformRegion(Out<Set::PlatformRegion> out_settings_platform_region);
|
||||||
Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
|
Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
|
||||||
|
|
||||||
void SetCpuBoostMode(HLERequestContext& ctx);
|
void SetCpuBoostMode(HLERequestContext& ctx);
|
||||||
|
@ -4,13 +4,16 @@
|
|||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/service/home_menu_functions.h"
|
#include "core/hle/service/am/service/home_menu_functions.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
|
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
: ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)},
|
WindowSystem& window_system)
|
||||||
m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} {
|
: ServiceFramework{system_, "IHomeMenuFunctions"}, m_window_system{window_system},
|
||||||
|
m_applet{std::move(applet)}, m_context{system, "IHomeMenuFunctions"},
|
||||||
|
m_pop_from_general_channel_event{m_context} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
|
{10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
|
||||||
@ -37,17 +40,20 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Ap
|
|||||||
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
|
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
|
||||||
|
|
||||||
Result IHomeMenuFunctions::RequestToGetForeground() {
|
Result IHomeMenuFunctions::RequestToGetForeground() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_window_system.RequestHomeMenuToGetForeground();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IHomeMenuFunctions::LockForeground() {
|
Result IHomeMenuFunctions::LockForeground() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_window_system.RequestLockHomeMenuIntoForeground();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IHomeMenuFunctions::UnlockForeground() {
|
Result IHomeMenuFunctions::UnlockForeground() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_window_system.RequestUnlockHomeMenuIntoForeground();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,10 +11,12 @@
|
|||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
struct Applet;
|
struct Applet;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
||||||
public:
|
public:
|
||||||
explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
|
explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
WindowSystem& window_system);
|
||||||
~IHomeMenuFunctions() override;
|
~IHomeMenuFunctions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -26,6 +28,7 @@ private:
|
|||||||
Result IsForceTerminateApplicationDisabledForDebug(
|
Result IsForceTerminateApplicationDisabledForDebug(
|
||||||
Out<bool> out_is_force_terminate_application_disabled_for_debug);
|
Out<bool> out_is_force_terminate_application_disabled_for_debug);
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
KernelHelpers::ServiceContext m_context;
|
KernelHelpers::ServiceContext m_context;
|
||||||
Event m_pop_from_general_channel_event;
|
Event m_pop_from_general_channel_event;
|
||||||
|
@ -47,20 +47,21 @@ ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
|||||||
Result ILibraryAppletAccessor::GetAppletStateChangedEvent(
|
Result ILibraryAppletAccessor::GetAppletStateChangedEvent(
|
||||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_event = m_broker->GetStateChangedEvent().GetHandle();
|
*out_event = m_applet->state_changed_event.GetHandle();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) {
|
Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_is_completed = m_broker->IsCompleted();
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
*out_is_completed = m_applet->is_completed;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) {
|
Result ILibraryAppletAccessor::GetResult() {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_result = m_applet->terminate_result;
|
std::scoped_lock lk{m_applet->lock};
|
||||||
R_SUCCEED();
|
R_RETURN(m_applet->terminate_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() {
|
Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() {
|
||||||
@ -77,7 +78,10 @@ Result ILibraryAppletAccessor::Start() {
|
|||||||
|
|
||||||
Result ILibraryAppletAccessor::RequestExit() {
|
Result ILibraryAppletAccessor::RequestExit() {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
m_applet->message_queue.RequestExit();
|
{
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->lifecycle_manager.RequestExit();
|
||||||
|
}
|
||||||
FrontendRequestExit();
|
FrontendRequestExit();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
Result IsCompleted(Out<bool> out_is_completed);
|
Result IsCompleted(Out<bool> out_is_completed);
|
||||||
Result GetResult(Out<Result> out_result);
|
Result GetResult();
|
||||||
Result PresetLibraryAppletGpuTimeSliceZero();
|
Result PresetLibraryAppletGpuTimeSliceZero();
|
||||||
Result Start();
|
Result Start();
|
||||||
Result RequestExit();
|
Result RequestExit();
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/am/library_applet_storage.h"
|
#include "core/hle/service/am/library_applet_storage.h"
|
||||||
|
#include "core/hle/service/am/process_creation.h"
|
||||||
#include "core/hle/service/am/service/library_applet_accessor.h"
|
#include "core/hle/service/am/service/library_applet_accessor.h"
|
||||||
#include "core/hle/service/am/service/library_applet_creator.h"
|
#include "core/hle/service/am/service/library_applet_creator.h"
|
||||||
#include "core/hle/service/am/service/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/am/window_system.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
@ -93,6 +95,7 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||||
|
WindowSystem& window_system,
|
||||||
std::shared_ptr<Applet> caller_applet,
|
std::shared_ptr<Applet> caller_applet,
|
||||||
AppletId applet_id,
|
AppletId applet_id,
|
||||||
LibraryAppletMode mode) {
|
LibraryAppletMode mode) {
|
||||||
@ -110,53 +113,38 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
|||||||
Firmware1700 = 17,
|
Firmware1700 = 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto process = std::make_unique<Process>(system);
|
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1700);
|
||||||
if (!process->Initialize(program_id, Firmware1400, Firmware1700)) {
|
if (!process) {
|
||||||
// Couldn't initialize the guest process
|
// Couldn't initialize the guest process
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto applet = std::make_shared<Applet>(system, std::move(process));
|
const auto applet = std::make_shared<Applet>(system, std::move(process), false);
|
||||||
applet->program_id = program_id;
|
applet->program_id = program_id;
|
||||||
applet->applet_id = applet_id;
|
applet->applet_id = applet_id;
|
||||||
applet->type = AppletType::LibraryApplet;
|
applet->type = AppletType::LibraryApplet;
|
||||||
applet->library_applet_mode = mode;
|
applet->library_applet_mode = mode;
|
||||||
|
applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden;
|
||||||
// Set focus state
|
|
||||||
switch (mode) {
|
|
||||||
case LibraryAppletMode::AllForeground:
|
|
||||||
case LibraryAppletMode::NoUi:
|
|
||||||
case LibraryAppletMode::PartialForeground:
|
|
||||||
case LibraryAppletMode::PartialForegroundIndirectDisplay:
|
|
||||||
applet->hid_registration.EnableAppletToGetInput(true);
|
|
||||||
applet->focus_state = FocusState::InFocus;
|
|
||||||
applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
|
|
||||||
break;
|
|
||||||
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
|
||||||
applet->hid_registration.EnableAppletToGetInput(false);
|
|
||||||
applet->focus_state = FocusState::NotInFocus;
|
|
||||||
applet->display_layer_manager.SetWindowVisibility(false);
|
|
||||||
applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto broker = std::make_shared<AppletDataBroker>(system);
|
auto broker = std::make_shared<AppletDataBroker>(system);
|
||||||
applet->caller_applet = caller_applet;
|
applet->caller_applet = caller_applet;
|
||||||
applet->caller_applet_broker = broker;
|
applet->caller_applet_broker = broker;
|
||||||
|
caller_applet->child_applets.push_back(applet);
|
||||||
|
|
||||||
system.GetAppletManager().InsertApplet(applet);
|
window_system.TrackApplet(applet, false);
|
||||||
|
|
||||||
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
|
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
|
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
|
||||||
|
WindowSystem& window_system,
|
||||||
std::shared_ptr<Applet> caller_applet,
|
std::shared_ptr<Applet> caller_applet,
|
||||||
AppletId applet_id,
|
AppletId applet_id,
|
||||||
LibraryAppletMode mode) {
|
LibraryAppletMode mode) {
|
||||||
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
|
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
|
||||||
|
|
||||||
auto process = std::make_unique<Process>(system);
|
auto process = std::make_unique<Process>(system);
|
||||||
auto applet = std::make_shared<Applet>(system, std::move(process));
|
auto applet = std::make_shared<Applet>(system, std::move(process), false);
|
||||||
applet->program_id = program_id;
|
applet->program_id = program_id;
|
||||||
applet->applet_id = applet_id;
|
applet->applet_id = applet_id;
|
||||||
applet->type = AppletType::LibraryApplet;
|
applet->type = AppletType::LibraryApplet;
|
||||||
@ -166,14 +154,19 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste
|
|||||||
applet->caller_applet = caller_applet;
|
applet->caller_applet = caller_applet;
|
||||||
applet->caller_applet_broker = storage;
|
applet->caller_applet_broker = storage;
|
||||||
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
|
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
|
||||||
|
caller_applet->child_applets.push_back(applet);
|
||||||
|
|
||||||
|
window_system.TrackApplet(applet, false);
|
||||||
|
|
||||||
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
|
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet)
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
: ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} {
|
WindowSystem& window_system)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletCreator"},
|
||||||
|
m_window_system{window_system}, m_applet{std::move(applet)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
||||||
{1, nullptr, "TerminateAllLibraryApplets"},
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||||
@ -195,10 +188,12 @@ Result ILibraryAppletCreator::CreateLibraryApplet(
|
|||||||
|
|
||||||
std::shared_ptr<ILibraryAppletAccessor> library_applet;
|
std::shared_ptr<ILibraryAppletAccessor> library_applet;
|
||||||
if (ShouldCreateGuestApplet(applet_id)) {
|
if (ShouldCreateGuestApplet(applet_id)) {
|
||||||
library_applet = CreateGuestApplet(system, m_applet, applet_id, library_applet_mode);
|
library_applet =
|
||||||
|
CreateGuestApplet(system, m_window_system, m_applet, applet_id, library_applet_mode);
|
||||||
}
|
}
|
||||||
if (!library_applet) {
|
if (!library_applet) {
|
||||||
library_applet = CreateFrontendApplet(system, m_applet, applet_id, library_applet_mode);
|
library_applet =
|
||||||
|
CreateFrontendApplet(system, m_window_system, m_applet, applet_id, library_applet_mode);
|
||||||
}
|
}
|
||||||
if (!library_applet) {
|
if (!library_applet) {
|
||||||
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
||||||
|
@ -12,10 +12,12 @@ namespace Service::AM {
|
|||||||
struct Applet;
|
struct Applet;
|
||||||
class ILibraryAppletAccessor;
|
class ILibraryAppletAccessor;
|
||||||
class IStorage;
|
class IStorage;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
||||||
public:
|
public:
|
||||||
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet);
|
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
WindowSystem& window_system);
|
||||||
~ILibraryAppletCreator() override;
|
~ILibraryAppletCreator() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -29,6 +31,7 @@ private:
|
|||||||
Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
|
Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
|
||||||
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process)
|
Kernel::KProcess* process, WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{
|
: ServiceFramework{system_, "ILibraryAppletProxy"},
|
||||||
std::move(applet)} {
|
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
@ -75,7 +75,7 @@ Result ILibraryAppletProxy::GetDebugFunctions(
|
|||||||
Result ILibraryAppletProxy::GetWindowController(
|
Result ILibraryAppletProxy::GetWindowController(
|
||||||
Out<SharedPointer<IWindowController>> out_window_controller) {
|
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_window_controller = std::make_shared<IWindowController>(system, m_applet);
|
*out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,8 @@ Result ILibraryAppletProxy::GetCommonStateGetter(
|
|||||||
Result ILibraryAppletProxy::GetLibraryAppletCreator(
|
Result ILibraryAppletProxy::GetLibraryAppletCreator(
|
||||||
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
|
*out_library_applet_creator =
|
||||||
|
std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +119,8 @@ Result ILibraryAppletProxy::GetAppletCommonFunctions(
|
|||||||
Result ILibraryAppletProxy::GetHomeMenuFunctions(
|
Result ILibraryAppletProxy::GetHomeMenuFunctions(
|
||||||
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
|
*out_home_menu_functions =
|
||||||
|
std::make_shared<IHomeMenuFunctions>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,11 +21,12 @@ class ILibraryAppletSelfAccessor;
|
|||||||
class IProcessWindingController;
|
class IProcessWindingController;
|
||||||
class ISelfController;
|
class ISelfController;
|
||||||
class IWindowController;
|
class IWindowController;
|
||||||
|
class WindowSystem;
|
||||||
|
|
||||||
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
||||||
public:
|
public:
|
||||||
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process);
|
Kernel::KProcess* process, WindowSystem& window_system);
|
||||||
~ILibraryAppletProxy();
|
~ILibraryAppletProxy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -47,6 +48,7 @@ private:
|
|||||||
Result GetGlobalStateController(
|
Result GetGlobalStateController(
|
||||||
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||||
|
|
||||||
|
WindowSystem& m_window_system;
|
||||||
Kernel::KProcess* const m_process;
|
Kernel::KProcess* const m_process;
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
@ -176,8 +176,7 @@ Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId
|
|||||||
|
|
||||||
Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
|
Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
|
||||||
LOG_INFO(Service_AM, "called");
|
LOG_INFO(Service_AM, "called");
|
||||||
system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid);
|
m_applet->process->Terminate();
|
||||||
m_broker->SignalCompletion();
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +86,7 @@ ISelfController::~ISelfController() {
|
|||||||
Result ISelfController::Exit() {
|
Result ISelfController::Exit() {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
// TODO
|
m_applet->process->Terminate();
|
||||||
system.Exit();
|
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@ -95,7 +94,16 @@ Result ISelfController::Exit() {
|
|||||||
Result ISelfController::LockExit() {
|
Result ISelfController::LockExit() {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
system.SetExitLocked(true);
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
|
||||||
|
if (m_applet->lifecycle_manager.GetExitRequested()) {
|
||||||
|
// With exit already requested, ignore and terminate immediately.
|
||||||
|
m_applet->process->Terminate();
|
||||||
|
} else {
|
||||||
|
// Otherwise, set exit lock state.
|
||||||
|
m_applet->exit_locked = true;
|
||||||
|
system.SetExitLocked(true);
|
||||||
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@ -103,10 +111,13 @@ Result ISelfController::LockExit() {
|
|||||||
Result ISelfController::UnlockExit() {
|
Result ISelfController::UnlockExit() {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
|
||||||
|
m_applet->exit_locked = false;
|
||||||
system.SetExitLocked(false);
|
system.SetExitLocked(false);
|
||||||
|
|
||||||
if (system.GetExitRequested()) {
|
if (m_applet->lifecycle_manager.GetExitRequested()) {
|
||||||
system.Exit();
|
m_applet->process->Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -155,7 +166,7 @@ Result ISelfController::SetOperationModeChangedNotification(bool enabled) {
|
|||||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
std::scoped_lock lk{m_applet->lock};
|
||||||
m_applet->operation_mode_changed_notification_enabled = enabled;
|
m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(enabled);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@ -164,17 +175,18 @@ Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) {
|
|||||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
std::scoped_lock lk{m_applet->lock};
|
||||||
m_applet->performance_mode_changed_notification_enabled = enabled;
|
m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(enabled);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) {
|
Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify,
|
LOG_INFO(Service_AM, "called, notify={} background={} suspend={}", notify, background, suspend);
|
||||||
background, suspend);
|
|
||||||
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
std::scoped_lock lk{m_applet->lock};
|
||||||
m_applet->focus_handling_mode = {notify, background, suspend};
|
m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(notify);
|
||||||
|
m_applet->lifecycle_manager.SetFocusHandlingMode(suspend);
|
||||||
|
m_applet->UpdateSuspensionStateLocked(true);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@ -183,7 +195,7 @@ Result ISelfController::SetRestartMessageEnabled(bool enabled) {
|
|||||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
std::scoped_lock lk{m_applet->lock};
|
||||||
m_applet->restart_message_enabled = enabled;
|
m_applet->lifecycle_manager.SetResumeNotificationEnabled(enabled);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@ -202,7 +214,8 @@ Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) {
|
|||||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
std::scoped_lock lk{m_applet->lock};
|
std::scoped_lock lk{m_applet->lock};
|
||||||
m_applet->out_of_focus_suspension_enabled = enabled;
|
m_applet->lifecycle_manager.SetOutOfFocusSuspendingEnabled(enabled);
|
||||||
|
m_applet->UpdateSuspensionStateLocked(false);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
Kernel::KProcess* process)
|
Kernel::KProcess* process, WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{
|
: ServiceFramework{system_, "ISystemAppletProxy"},
|
||||||
std::move(applet)} {
|
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
@ -75,7 +75,7 @@ Result ISystemAppletProxy::GetDebugFunctions(
|
|||||||
Result ISystemAppletProxy::GetWindowController(
|
Result ISystemAppletProxy::GetWindowController(
|
||||||
Out<SharedPointer<IWindowController>> out_window_controller) {
|
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_window_controller = std::make_shared<IWindowController>(system, m_applet);
|
*out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,14 +96,15 @@ Result ISystemAppletProxy::GetCommonStateGetter(
|
|||||||
Result ISystemAppletProxy::GetLibraryAppletCreator(
|
Result ISystemAppletProxy::GetLibraryAppletCreator(
|
||||||
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
|
*out_library_applet_creator =
|
||||||
|
std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ISystemAppletProxy::GetApplicationCreator(
|
Result ISystemAppletProxy::GetApplicationCreator(
|
||||||
Out<SharedPointer<IApplicationCreator>> out_application_creator) {
|
Out<SharedPointer<IApplicationCreator>> out_application_creator) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_application_creator = std::make_shared<IApplicationCreator>(system);
|
*out_application_creator = std::make_shared<IApplicationCreator>(system, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +118,8 @@ Result ISystemAppletProxy::GetAppletCommonFunctions(
|
|||||||
Result ISystemAppletProxy::GetHomeMenuFunctions(
|
Result ISystemAppletProxy::GetHomeMenuFunctions(
|
||||||
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
*out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
|
*out_home_menu_functions =
|
||||||
|
std::make_shared<IHomeMenuFunctions>(system, m_applet, m_window_system);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user