Compare commits

..

4 Commits

Author SHA1 Message Date
xbzk 4648d406b4 [fs] debug_knobs controlled delay (us) for IStorage::Read 2026-08-28 08:40:28 -03:00
xbzk 926cc3185f [settings] make debug_knobs per-game wise 2026-08-25 22:35:04 -03:00
xbzk cc62c5644e [android] Expose log filter setting 2026-08-25 22:35:04 -03:00
xbzk d81579ba51 [core] Add compact guest backtrace decoder 2026-08-25 22:35:04 -03:00
263 changed files with 2148 additions and 3183 deletions
-20
View File
@@ -69,26 +69,6 @@ if (YUZU_STATIC_ROOM)
set(fmt_FORCE_BUNDLED ON) set(fmt_FORCE_BUNDLED ON)
endif() endif()
# my unity/jumbo build
option(ENABLE_UNITY_BUILD "Enable Unity/Jumbo build" OFF)
# 0 compiles all files in
# not ideal, but if you're going gung-ho with a unity build, expect failure
# MSVC physically can't compile that many files into one TU, so we limit it to 100.
if (MSVC)
set(_unity_default 100)
else()
set(_unity_default 0)
endif()
set(UNITY_BATCH_SIZE ${_unity_default} CACHE STRING "Unity build batch size")
if(MSVC AND ENABLE_UNITY_BUILD)
message(STATUS "Unity build")
# Unity builds need big objects for MSVC...
add_compile_options(/bigobj)
endif()
# qt stuff # qt stuff
option(ENABLE_QT "Enable the Qt frontend" ON) option(ENABLE_QT "Enable the Qt frontend" ON)
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
-1
View File
@@ -39,7 +39,6 @@ These options control dependencies.
- This option is subject for removal. - This option is subject for removal.
- `YUZU_TESTS` (ON) Compile tests - requires Catch2 - `YUZU_TESTS` (ON) Compile tests - requires Catch2
- `ENABLE_LTO` (OFF) Enable link-time optimization - `ENABLE_LTO` (OFF) Enable link-time optimization
- `ENABLE_UNITY_BUILD` (OFF) Enables "Unity/Jumbo" builds
- Not recommended on Windows - Not recommended on Windows
- UNIX may be better off appending `-flto=thin` to compiler args - UNIX may be better off appending `-flto=thin` to compiler args
- `USE_FASTER_LINKER` (OFF) Check if a faster linker is available - `USE_FASTER_LINKER` (OFF) Check if a faster linker is available
-5
View File
@@ -7,11 +7,6 @@
# Enable modules to include each other's files # Enable modules to include each other's files
include_directories(.) include_directories(.)
if (ENABLE_UNITY_BUILD)
set(CMAKE_UNITY_BUILD ON)
set(CMAKE_UNITY_BUILD_BATCH_SIZE ${UNITY_BATCH_SIZE})
endif()
# Dynarmic # Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM) if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
add_subdirectory(dynarmic) add_subdirectory(dynarmic)
+1 -1
View File
@@ -188,7 +188,7 @@ android {
create("mainline") { create("mainline") {
dimension = "version" dimension = "version"
isDefault = true isDefault = true
minSdk = 33 minSdk = 30
manifestPlaceholders += mapOf("appNameBase" to "Eden") manifestPlaceholders += mapOf("appNameBase" to "Eden")
resValue("string", "app_name_suffixed", "Eden") resValue("string", "app_name_suffixed", "Eden")
@@ -11,6 +11,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
enum class StringSetting(override val key: String) : AbstractStringSetting { enum class StringSetting(override val key: String) : AbstractStringSetting {
DRIVER_PATH("driver_path"), DRIVER_PATH("driver_path"),
DEVICE_NAME("device_name"), DEVICE_NAME("device_name"),
LOG_FILTER("log_filter"),
PROGRAM_ARGS("program_args"), PROGRAM_ARGS("program_args"),
WEB_TOKEN("eden_token"), WEB_TOKEN("eden_token"),
@@ -1032,6 +1032,13 @@ abstract class SettingsItem(
descriptionId = R.string.use_auto_stub_description descriptionId = R.string.use_auto_stub_description
) )
) )
put(
StringInputSetting(
StringSetting.LOG_FILTER,
titleId = R.string.log_filter,
descriptionId = R.string.log_filter_description
)
)
put( put(
SpinBoxSetting( SpinBoxSetting(
ShortSetting.DEBUG_KNOBS, ShortSetting.DEBUG_KNOBS,
@@ -1322,6 +1322,7 @@ class SettingsFragmentPresenter(
add(HeaderSetting(R.string.log)) add(HeaderSetting(R.string.log))
add(BooleanSetting.DEBUG_FLUSH_BY_LINE.key) add(BooleanSetting.DEBUG_FLUSH_BY_LINE.key)
add(StringSetting.LOG_FILTER.key)
} }
add(HeaderSetting(R.string.general)) add(HeaderSetting(R.string.general))
+4 -59
View File
@@ -76,7 +76,6 @@ extern "C" {
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h" #include "core/frontend/applets/web_browser.h"
#include "common/android/applets/web_browser.h" #include "common/android/applets/web_browser.h"
#include "core/file_sys/common_funcs.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/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
@@ -312,23 +311,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
ConfigureFilesystemProvider(filepath); ConfigureFilesystemProvider(filepath);
// Load the ROM. // Load the ROM.
const u64 previous_program_id =
program_index != 0 && m_next_program_id.load() >
static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)
? m_next_program_id.load()
: 0;
Service::AM::FrontendAppletParameters params{ Service::AM::FrontendAppletParameters params{
.program_id = previous_program_id,
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id), .applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated .launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
: Service::AM::LaunchType::ApplicationInitiated, : Service::AM::LaunchType::ApplicationInitiated,
.program_index = static_cast<s32>(program_index), .program_index = static_cast<s32>(program_index),
.previous_program_index =
previous_program_id != 0
? static_cast<s32>(previous_program_id -
FileSys::GetBaseTitleID(previous_program_id))
: -1,
}; };
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params); m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
@@ -341,12 +328,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.GetCpuManager().OnGpuReady(); m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([&] { HaltEmulation(); }); m_system.RegisterExitCallback([&] { HaltEmulation(); });
m_system.RegisterApplicationChangedCallback(
[&](u64 changed_program_id) { RequestDiskShaderCacheReload(changed_program_id); });
// Register an ExecuteProgram callback such that Core can execute a sub-program // Register an ExecuteProgram callback such that Core can execute a sub-program
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) { m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
m_next_program_id = m_system.GetApplicationProcessProgramID();
m_next_program_index = program_index_; m_next_program_index = program_index_;
EmulationSession::GetInstance().HaltEmulation(); EmulationSession::GetInstance().HaltEmulation();
}); });
@@ -424,58 +407,20 @@ void EmulationSession::RunEmulation() {
} }
while (true) { while (true) {
std::optional<u64> reload_title;
{ {
[[maybe_unused]] std::unique_lock lock(m_mutex); [[maybe_unused]] std::unique_lock lock(m_mutex);
if (m_cv.wait_for(lock, std::chrono::milliseconds(800), [&]() { if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
return !m_is_running || m_pending_shader_cache_title.has_value(); [&]() { return !m_is_running; })) {
})) { // Emulation halted.
if (!m_is_running) { break;
break;
}
reload_title = std::exchange(m_pending_shader_cache_title, std::nullopt);
} }
} }
if (reload_title.has_value())
ReloadDiskShaderCache(*reload_title);
} }
// Reset current applet ID. // Reset current applet ID.
m_applet_id = static_cast<int>(Service::AM::AppletId::Application); m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
} }
void EmulationSession::RequestDiskShaderCacheReload(u64 program_id) {
{
std::scoped_lock lock(m_mutex);
m_pending_shader_cache_title = program_id;
}
m_cv.notify_one();
}
void EmulationSession::ReloadDiskShaderCache(u64 program_id) {
if (!Settings::values.use_disk_shader_cache.GetValue())
return;
LOG_INFO(Frontend, "Reloading disk shader cache for {:016X}", program_id);
const bool was_paused = m_is_paused;
m_system.Pause();
m_system.GPU().WaitForIdle();
m_system.GPU().ObtainContext();
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
m_system.Renderer().ReadRasterizer()->LoadDiskResources(program_id, std::stop_token{},
LoadDiskCacheProgress);
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
m_system.GPU().ReleaseContext();
if (!was_paused)
m_system.Run();
}
Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() { Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() {
return m_software_keyboard; return m_software_keyboard;
} }
-6
View File
@@ -4,8 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <optional>
#include <android/native_window_jni.h> #include <android/native_window_jni.h>
#include "common/android/applets/software_keyboard.h" #include "common/android/applets/software_keyboard.h"
#include "core/core.h" #include "core/core.h"
@@ -46,7 +44,6 @@ public:
void HaltEmulation(); void HaltEmulation();
void RunEmulation(); void RunEmulation();
void ShutdownEmulation(); void ShutdownEmulation();
void RequestDiskShaderCacheReload(u64 program_id);
const Core::PerfStatsResults& PerfStats(); const Core::PerfStatsResults& PerfStats();
int ShadersBuilding(); int ShadersBuilding();
@@ -68,7 +65,6 @@ private:
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max); static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
static void OnEmulationStopped(Core::SystemResultStatus result); static void OnEmulationStopped(Core::SystemResultStatus result);
static void ChangeProgram(std::size_t program_index); static void ChangeProgram(std::size_t program_index);
void ReloadDiskShaderCache(u64 program_id);
private: private:
// Window management // Window management
@@ -87,7 +83,6 @@ private:
Common::Android::SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; Common::Android::SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
int m_applet_id{1}; int m_applet_id{1};
std::optional<u64> m_pending_shader_cache_title;
// GPU driver parameters // GPU driver parameters
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
@@ -98,5 +93,4 @@ private:
// Program index for next boot // Program index for next boot
std::atomic<s32> m_next_program_index = -1; std::atomic<s32> m_next_program_index = -1;
std::atomic<u64> m_next_program_id = 0;
}; };
@@ -636,6 +636,8 @@
<string name="log">Logging</string> <string name="log">Logging</string>
<string name="flush_by_line">Flush debug logs by line</string> <string name="flush_by_line">Flush debug logs by line</string>
<string name="flush_by_line_description">Flushes debugging logs on each line written, making debugging easier in cases of crashing or freezing.</string> <string name="flush_by_line_description">Flushes debugging logs on each line written, making debugging easier in cases of crashing or freezing.</string>
<string name="log_filter">Log filter</string>
<string name="log_filter_description">Controls Eden\'s log categories. Example: *:Info Service.LM:Debug</string>
<!-- GPU Logging strings --> <!-- GPU Logging strings -->
<string name="gpu_logging_header">GPU Logging</string> <string name="gpu_logging_header">GPU Logging</string>
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,11 +5,17 @@
#include "common/assert.h" #include "common/assert.h"
namespace AudioCore::ADSP::OpusDecoder { namespace AudioCore::ADSP::OpusDecoder {
namespace {
bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
} // namespace
u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) { u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) {
if (channel_count == 1 || channel_count == 2) if (!IsValidChannelCount(channel_count)) {
return 0; return 0;
return u32(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count); }
return static_cast<u32>(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count);
} }
OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) { OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) {
@@ -22,6 +22,10 @@ namespace AudioCore::ADSP::OpusDecoder {
namespace { namespace {
constexpr size_t OpusStreamCountMax = 255; constexpr size_t OpusStreamCountMax = 255;
bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
bool IsValidMultiStreamChannelCount(u32 channel_count) { bool IsValidMultiStreamChannelCount(u32 channel_count) {
return channel_count <= OpusStreamCountMax; return channel_count <= OpusStreamCountMax;
} }
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,12 +7,13 @@
namespace AudioCore::ADSP::OpusDecoder { namespace AudioCore::ADSP::OpusDecoder {
namespace { namespace {
constexpr u32 OpusStreamCountMax = 255; bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) {
return total_stream_count > 0 && total_stream_count <= OpusStreamCountMax && return total_stream_count > 0 && static_cast<s32>(stereo_stream_count) >= 0 &&
static_cast<s32>(stereo_stream_count) >= 0 && stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count);
stereo_stream_count <= total_stream_count;
} }
} // namespace } // namespace
-3
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
+4 -4
View File
@@ -14,16 +14,14 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event.h"
namespace AudioCore::AudioIn {
// See texture_cache/util.h // See texture_cache/util.h
template<typename T, size_t N> template<typename T, size_t N>
#if BOOST_VERSION >= 108100 || __GNUC__ > 12 #if BOOST_VERSION >= 108100 || __GNUC__ > 12
[[nodiscard]] static inline boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) { [[nodiscard]] boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
return v; return v;
} }
#else #else
[[nodiscard]] static inline std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) { [[nodiscard]] std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
std::vector<T> u; std::vector<T> u;
for (auto const& e : v) for (auto const& e : v)
u.push_back(e); u.push_back(e);
@@ -31,6 +29,8 @@ template<typename T, size_t N>
} }
#endif #endif
namespace AudioCore::AudioIn {
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_) System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
: system{system_}, buffer_event{event_}, : system{system_}, buffer_event{event_},
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {} session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -108,7 +105,7 @@ Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 chan
shared_memory.host_send_data[4] = total_stream_count; shared_memory.host_send_data[4] = total_stream_count;
shared_memory.host_send_data[5] = stereo_stream_count; shared_memory.host_send_data[5] = stereo_stream_count;
ASSERT(channel_count <= shared_memory.channel_mapping.size()); ASSERT(channel_count <= MaxChannels);
std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8)); std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8));
opus_decoder.Send(ADSP::Direction::DSP, opus_decoder.Send(ADSP::Direction::DSP,
+4 -3
View File
@@ -14,15 +14,14 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event.h"
namespace AudioCore::AudioOut {
// See texture_cache/util.h // See texture_cache/util.h
template<typename T, size_t N> template<typename T, size_t N>
#if BOOST_VERSION >= 108100 || __GNUC__ > 12 #if BOOST_VERSION >= 108100 || __GNUC__ > 12
[[nodiscard]] static inline boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) { [[nodiscard]] boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
return v; return v;
} }
#else #else
[[nodiscard]] static inline std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) { [[nodiscard]] std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
std::vector<T> u; std::vector<T> u;
for (auto const& e : v) for (auto const& e : v)
u.push_back(e); u.push_back(e);
@@ -30,6 +29,8 @@ template<typename T, size_t N>
} }
#endif #endif
namespace AudioCore::AudioOut {
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_) System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
: system{system_}, buffer_event{event_}, : system{system_}, buffer_event{event_},
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {} session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -16,7 +16,7 @@ namespace AudioCore::Renderer {
* @param memory - Core memory for writing. * @param memory - Core memory for writing.
* @param aux_info - Memory address pointing to the AuxInfo to reset. * @param aux_info - Memory address pointing to the AuxInfo to reset.
*/ */
static void CaptureResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_info) { static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_info) {
if (aux_info == 0) { if (aux_info == 0) {
LOG_ERROR(Service_Audio, "Aux info is 0!"); LOG_ERROR(Service_Audio, "Aux info is 0!");
return; return;
@@ -134,7 +134,7 @@ void CaptureCommand::Process(const AudioRenderer::CommandListProcessor& processo
WriteAuxBufferDsp(*processor.memory, send_buffer_info, send_buffer, count_max, input_buffer, WriteAuxBufferDsp(*processor.memory, send_buffer_info, send_buffer, count_max, input_buffer,
processor.sample_count, write_offset, update_count); processor.sample_count, write_offset, update_count);
} else { } else {
CaptureResetAuxBufferDsp(*processor.memory, send_buffer_info); ResetAuxBufferDsp(*processor.memory, send_buffer_info);
} }
} }
+27 -28
View File
@@ -19,23 +19,6 @@
namespace AudioCore::Sink { namespace AudioCore::Sink {
namespace { namespace {
[[nodiscard]] bool InitializeAudio() {
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
// See https://github.com/PCSX2/pcsx2/pull/12312
// "SDL and cubeb backends previously resulted in different names for the output which
// caused them be identified as different applications by the OS."
//
// Keep in sync with cubeb_sink.cpp name.
SDL_SetHint("SDL_AUDIO_DEVICE_APP_NAME", "yuzu Latency Getter");
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
return false;
}
}
return true;
}
SDL_AudioDeviceID FindAudioDeviceByName(const std::string& device_name, bool capture) { SDL_AudioDeviceID FindAudioDeviceByName(const std::string& device_name, bool capture) {
int device_count = 0; int device_count = 0;
SDL_AudioDeviceID* devices = capture ? SDL_GetAudioRecordingDevices(&device_count) SDL_AudioDeviceID* devices = capture ? SDL_GetAudioRecordingDevices(&device_count)
@@ -221,14 +204,20 @@ private:
}; };
SDLSink::SDLSink(std::string_view target_device_name) { SDLSink::SDLSink(std::string_view target_device_name) {
if (InitializeAudio()) { if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (target_device_name != auto_device_name && !target_device_name.empty()) { if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
output_device = target_device_name; LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
} else { return;
output_device.clear();
} }
device_channels = 2;
} }
if (target_device_name != auto_device_name && !target_device_name.empty()) {
output_device = target_device_name;
} else {
output_device.clear();
}
device_channels = 2;
} }
SDLSink::~SDLSink() = default; SDLSink::~SDLSink() = default;
@@ -276,10 +265,15 @@ void SDLSink::SetSystemVolume(f32 volume) {
} }
std::vector<std::string> ListSDLSinkDevices(bool capture) { std::vector<std::string> ListSDLSinkDevices(bool capture) {
if (!InitializeAudio())
return {}; //no devices
std::vector<std::string> device_list; std::vector<std::string> device_list;
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
return {};
}
}
int device_count = 0; int device_count = 0;
SDL_AudioDeviceID* devices = SDL_AudioDeviceID* devices =
capture ? SDL_GetAudioRecordingDevices(&device_count) capture ? SDL_GetAudioRecordingDevices(&device_count)
@@ -310,8 +304,13 @@ bool IsSDLSuitable() {
return false; return false;
#else #else
// Check SDL can init // Check SDL can init
if (!InitializeAudio()! if (!SDL_WasInit(SDL_INIT_AUDIO)) {
return false; if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
LOG_ERROR(Audio_Sink, "SDL failed to init, it is not suitable. Error: {}",
SDL_GetError());
return false;
}
}
// We can set any latency frequency we want with SDL, so no need to check that. // We can set any latency frequency we want with SDL, so no need to check that.
+8 -9
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2011 Google, Inc. // SPDX-FileCopyrightText: 2011 Google, Inc.
// SPDX-FileContributor: Geoff Pike // SPDX-FileContributor: Geoff Pike
// SPDX-FileContributor: Jyrki Alakuijala // SPDX-FileContributor: Jyrki Alakuijala
@@ -30,6 +27,8 @@
#define WORDS_BIGENDIAN 1 #define WORDS_BIGENDIAN 1
#endif #endif
using namespace std;
namespace Common { namespace Common {
static u64 unaligned_load64(const char* p) { static u64 unaligned_load64(const char* p) {
@@ -136,18 +135,18 @@ static u64 HashLen17to32(const char* s, size_t len) {
// Return a 16-byte hash for 48 bytes. Quick and dirty. // Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b. // Callers do best to use "random-looking" values for a and b.
static std::pair<u64, u64> WeakHashLen32WithSeeds(u64 w, u64 x, u64 y, u64 z, u64 a, u64 b) { static pair<u64, u64> WeakHashLen32WithSeeds(u64 w, u64 x, u64 y, u64 z, u64 a, u64 b) {
a += w; a += w;
b = Rotate(b + a + z, 21); b = Rotate(b + a + z, 21);
u64 c = a; u64 c = a;
a += x; a += x;
a += y; a += y;
b += Rotate(a, 44); b += Rotate(a, 44);
return std::make_pair(a + z, b + c); return make_pair(a + z, b + c);
} }
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
static std::pair<u64, u64> WeakHashLen32WithSeeds(const char* s, u64 a, u64 b) { static pair<u64, u64> WeakHashLen32WithSeeds(const char* s, u64 a, u64 b) {
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a, return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
b); b);
} }
@@ -190,8 +189,8 @@ u64 CityHash64(const char* s, size_t len) {
u64 x = Fetch64(s + len - 40); u64 x = Fetch64(s + len - 40);
u64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); u64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
u64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); u64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
std::pair<u64, u64> v = WeakHashLen32WithSeeds(s + len - 64, len, z); pair<u64, u64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
std::pair<u64, u64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); pair<u64, u64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
x = x * k1 + Fetch64(s); x = x * k1 + Fetch64(s);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -259,7 +258,7 @@ u128 CityHash128WithSeed(const char* s, size_t len, u128 seed) {
// We expect len >= 128 to be the common case. Keep 56 bytes of state: // We expect len >= 128 to be the common case. Keep 56 bytes of state:
// v, w, x, y, and z. // v, w, x, y, and z.
std::pair<u64, u64> v, w; pair<u64, u64> v, w;
u64 x = seed[0]; u64 x = seed[0];
u64 y = seed[1]; u64 y = seed[1];
u64 z = len * k1; u64 z = len * k1;
-2
View File
@@ -16,5 +16,3 @@
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#undef INVALID_SOCKET
+4 -4
View File
@@ -224,7 +224,7 @@ struct ColorConsoleBackend final : public Backend {
auto const df = GetDirectFormatArgs(entry); auto const df = GetDirectFormatArgs(entry);
// more restrictive, because take for example this simple prelude: // more restrictive, because take for example this simple prelude:
// [ 50.872256] Config <Info> common/settings.cpp:142:LogSettings: // [ 50.872256] Config <Info> common/settings.cpp:142:LogSettings:
char buffer[256]; char buffer[128];
auto result = fmt::format_to_n(buffer, sizeof(buffer) - 1, "\x1b{}[{:4d}.{:06d}] {} <{}> {}:{}:{}: ", color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message); auto result = fmt::format_to_n(buffer, sizeof(buffer) - 1, "\x1b{}[{:4d}.{:06d}] {} <{}> {}:{}:{}: ", color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message);
std::fwrite(buffer, 1, (std::min)(sizeof(buffer) - 1, result.size), stdout); std::fwrite(buffer, 1, (std::min)(sizeof(buffer) - 1, result.size), stdout);
std::fwrite(entry.message, 1, entry.message_len, stdout); std::fwrite(entry.message, 1, entry.message_len, stdout);
@@ -425,14 +425,14 @@ void SetColorConsoleBackendEnabled(bool enabled) {
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) { void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) {
if (logging_instance && logging_instance->filter.CheckMessage(log_class, log_level)) { if (logging_instance && logging_instance->filter.CheckMessage(log_class, log_level)) {
auto const flush = ::Settings::values.log_flush_line.GetValue();
char buffer[BUFSIZ]; char buffer[BUFSIZ];
auto result = fmt::vformat_to_n(buffer, sizeof(buffer) - 1, format, args); auto result = fmt::vformat_to_n(buffer, sizeof(buffer) - 1, format, args);
buffer[(std::min)(result.size, sizeof(buffer) - 1)] = '\0'; buffer[result.size] = '\0';
auto const flush = ::Settings::values.log_flush_line.GetValue();
logging_instance->ForEachBackend([=](Backend& backend) { logging_instance->ForEachBackend([=](Backend& backend) {
backend.Write(Entry{ backend.Write(Entry{
.message = buffer, .message = buffer,
.message_len = (std::min)(result.size, sizeof(buffer) - 1), .message_len = (std::min)(sizeof(buffer) - 1, result.size),
.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin), .timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin),
.log_class = log_class, .log_class = log_class,
.log_level = log_level, .log_level = log_level,
+4 -2
View File
@@ -132,9 +132,11 @@ void LogSettings() {
} }
} }
} }
LOG_INFO(Config, "Eden Configuration:");
std::string settings_str{};
for (auto const& e : settings_list) for (auto const& e : settings_list)
LOG_INFO(Config, "{}", e); settings_str += e;
LOG_INFO(Config, "Eden Configuration:\n{}", settings_str);
#define LOG_PATH(NAME) \ #define LOG_PATH(NAME) \
LOG_INFO(Config, #NAME ": {}", Common::FS::PathToUTF8String(Common::FS::GetEdenPath(Common::FS::EdenPath::NAME))) LOG_INFO(Config, #NAME ": {}", Common::FS::PathToUTF8String(Common::FS::GetEdenPath(Common::FS::EdenPath::NAME)))
LOG_PATH(CacheDir); LOG_PATH(CacheDir);
+1 -1
View File
@@ -904,7 +904,7 @@ struct Values {
0, 0,
65535, 65535,
"debug_knobs", "debug_knobs",
Category::Debugging, Category::System,
Specialization::Countable, Specialization::Countable,
true, true,
true}; true};
+2
View File
@@ -7,4 +7,6 @@
#define STB_IMAGE_IMPLEMENTATION 1 #define STB_IMAGE_IMPLEMENTATION 1
#define STB_IMAGE_RESIZE_IMPLEMENTATION 1 #define STB_IMAGE_RESIZE_IMPLEMENTATION 1
#define STB_IMAGE_WRITE_IMPLEMENTATION 1 #define STB_IMAGE_WRITE_IMPLEMENTATION 1
#define STBI_ONLY_JPEG 1
#include "common/stb.h" #include "common/stb.h"
-1
View File
@@ -7,7 +7,6 @@
#pragma once #pragma once
#define STBI_ONLY_JPEG 1 #define STBI_ONLY_JPEG 1
#define STBI_WRITE_NO_STDIO 1
#include <stb_image.h> #include <stb_image.h>
#include <stb_image_resize.h> #include <stb_image_resize.h>
#include <stb_image_write.h> #include <stb_image_write.h>
+182 -14
View File
@@ -3,14 +3,158 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <array>
#include <cctype>
#include <string>
#include <string_view>
#include <vector>
#include "common/logging.h" #include "common/logging.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/debug.h" #include "core/arm/debug.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_memory_block.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc_types.h"
namespace Core { namespace Core {
namespace {
constexpr std::size_t GuestStringProbeBytes = 0x100;
constexpr std::size_t StackProbeWords = 96;
constexpr std::size_t MaxGuestStringLogs = 16;
constexpr std::size_t MaxBacktraceFrames = 64;
constexpr std::size_t MinGuestStringLength = 4;
std::string SanitizeGuestString(std::string_view text) {
std::string sanitized;
sanitized.reserve(text.size());
for (const char ch : text) {
switch (ch) {
case '\\':
sanitized += "\\\\";
break;
case '"':
sanitized += "\\\"";
break;
default:
sanitized += ch;
break;
}
}
return sanitized;
}
bool IsUsefulGuestString(std::string_view text) {
if (text.size() < MinGuestStringLength) {
return false;
}
std::size_t alpha_numeric_count{};
for (const char ch : text) {
const auto byte = static_cast<unsigned char>(ch);
if (std::isprint(byte) == 0) {
return false;
}
if (std::isalnum(byte) != 0) {
alpha_numeric_count++;
}
}
return alpha_numeric_count > 0;
}
bool QueryGuestMemoryInfo(Kernel::KProcess* process, u64 address,
Kernel::Svc::MemoryInfo* out_info) {
if (address == 0) {
return false;
}
Kernel::KMemoryInfo mem_info{};
Kernel::Svc::PageInfo page_info{};
if (process->GetPageTable().QueryInfo(&mem_info, &page_info, address).IsFailure()) {
return false;
}
*out_info = mem_info.GetSvcMemoryInfo();
return true;
}
void LogGuestStringCandidate(Kernel::KProcess* process, u64 address, std::string_view label,
std::vector<u64>& logged_strings) {
if (logged_strings.size() >= MaxGuestStringLogs) {
return;
}
if (std::find(logged_strings.begin(), logged_strings.end(), address) != logged_strings.end()) {
return;
}
Kernel::Svc::MemoryInfo mem_info{};
if (!QueryGuestMemoryInfo(process, address, &mem_info)) {
return;
}
if (mem_info.state == Kernel::Svc::MemoryState::Free ||
mem_info.permission == Kernel::Svc::MemoryPermission::None) {
return;
}
if (address < mem_info.base_address) {
return;
}
const u64 region_offset = address - mem_info.base_address;
if (region_offset >= mem_info.size) {
return;
}
const u64 available_bytes = mem_info.size - region_offset;
const auto probe_size =
static_cast<std::size_t>(std::min<u64>(GuestStringProbeBytes, available_bytes));
if (probe_size < MinGuestStringLength ||
!process->GetMemory().IsValidVirtualAddressRange(address, probe_size)) {
return;
}
const auto text = process->GetMemory().ReadCString(address, probe_size);
if (!IsUsefulGuestString(text)) {
return;
}
logged_strings.push_back(address);
LOG_ERROR(Core_ARM, "Guest backtrace string {:02}: {}={:016X} \"{}\"",
logged_strings.size() - 1, label, address, SanitizeGuestString(text));
}
void LogStackStringCandidates(Kernel::KProcess* process, u64 base, std::string_view label,
std::vector<u64>& logged_strings) {
if (base == 0) {
return;
}
auto& memory = process->GetMemory();
for (std::size_t i = 0; i < StackProbeWords; i++) {
const u64 address = base + i * sizeof(u64);
if (!memory.IsValidVirtualAddressRange(address, sizeof(u64))) {
break;
}
u64 value{};
if (!memory.ReadBlock(address, &value, sizeof(value))) {
continue;
}
LogGuestStringCandidate(process, value, fmt::format("{}+{:03X}", label, i * sizeof(u64)),
logged_strings);
}
}
} // namespace
void ArmInterface::LogBacktrace(Kernel::KProcess* process) const { void ArmInterface::LogBacktrace(Kernel::KProcess* process) const {
Kernel::Svc::ThreadContext ctx; Kernel::Svc::ThreadContext ctx;
this->GetContext(ctx); this->GetContext(ctx);
@@ -26,21 +170,45 @@ void ArmInterface::LogBacktrace(Kernel::KProcess* process) const {
ctx.r[28], ctx.fp, ctx.lr, ctx.sp, ctx.r[28], ctx.fp, ctx.lr, ctx.sp,
}; };
std::string msg = fmt::format("Backtrace @ PC={:016X}\n", ctx.pc); LOG_ERROR(Core_ARM,
for (size_t i = 0; i < 32; i += 4) "Guest backtrace context: process=\"{}\" pid={} program_id={:016X} pc={:016X} "
msg += fmt::format("R{:02}={:016X} R{:02}={:016X} R{:02}={:016X} R{:02}={:016X}\n", "lr={:016X} fp={:016X} sp={:016X} pstate={:08X}",
i + 0, xreg[i + 0], i + 1, xreg[i + 1], process->GetName(), process->GetProcessId(), process->GetProgramId(), ctx.pc,
i + 2, xreg[i + 2], i + 3, xreg[i + 3]); ctx.lr, ctx.fp, ctx.sp, ctx.pstate);
for (size_t i = 0; i < 32; i += 2)
msg += fmt::format("V{:02}={:016X}_{:016X} V{:02}={:016X}_{:016X}\n", std::vector<u64> logged_strings;
i + 0, ctx.v[i + 0][0], ctx.v[i + 0][1], for (size_t i = 0; i < xreg.size(); i++) {
i + 1, ctx.v[i + 1][0], ctx.v[i + 1][1]); LogGuestStringCandidate(process, xreg[i], fmt::format("R{:02}", i), logged_strings);
msg += fmt::format("PSTATE={:08X} FPCR={:08X} FPSR={:08X} TPIDR={:016X}\n", ctx.pstate, ctx.fpcr, ctx.fpsr, ctx.tpidr); }
msg += fmt::format("{:20}{:20}{:20}{:20}{}\n", "Module", "Address", "Original Address", "Offset", "Symbol"); LogStackStringCandidates(process, ctx.sp, "SP", logged_strings);
if (ctx.fp != ctx.sp) {
LogStackStringCandidates(process, ctx.fp, "FP", logged_strings);
}
if (logged_strings.empty()) {
LOG_ERROR(Core_ARM, "Guest backtrace strings: none found in registers or stack");
}
auto const backtrace = GetBacktraceFromContext(process, ctx); auto const backtrace = GetBacktraceFromContext(process, ctx);
for (auto const& entry : backtrace) for (size_t i = 0; i < std::min(backtrace.size(), MaxBacktraceFrames); i++) {
msg += fmt::format("{:20}{:016X} {:016X} {:016X} {}\n", entry.module, entry.address, entry.original_address, entry.offset, entry.name); const auto& entry = backtrace[i];
LOG_ERROR(Core_ARM, "{}", msg); if (entry.original_address == 0) {
break;
}
if (entry.name.empty()) {
LOG_ERROR(Core_ARM, "Guest backtrace frame {:03}: {}+0x{:X} pc={:016X} mapped={:016X}",
i, entry.module, entry.offset, entry.original_address, entry.address);
} else {
LOG_ERROR(Core_ARM,
"Guest backtrace frame {:03}: {}+0x{:X} pc={:016X} mapped={:016X} symbol={}",
i, entry.module, entry.offset, entry.original_address, entry.address,
entry.name);
}
}
if (backtrace.size() > MaxBacktraceFrames) {
LOG_ERROR(Core_ARM, "Guest backtrace truncated: logged={} total={}", MaxBacktraceFrames,
backtrace.size());
}
} }
const Kernel::DebugWatchpoint* ArmInterface::MatchingWatchpoint( const Kernel::DebugWatchpoint* ArmInterface::MatchingWatchpoint(
+8 -7
View File
@@ -7,18 +7,19 @@
#pragma once #pragma once
#include <dynarmic/interface/halt_reason.h> #include <dynarmic/interface/halt_reason.h>
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
namespace Core { namespace Core {
inline constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step; constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step;
inline constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort; constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort;
inline constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2; constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2;
inline constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3; constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3;
inline constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4; constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4;
inline constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6; constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6;
[[nodiscard]] inline constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) { constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
static_assert(u64(HaltReason::StepThread) == u64(StepThread)); static_assert(u64(HaltReason::StepThread) == u64(StepThread));
static_assert(u64(HaltReason::DataAbort) == u64(DataAbort)); static_assert(u64(HaltReason::DataAbort) == u64(DataAbort));
static_assert(u64(HaltReason::BreakLoop) == u64(BreakLoop)); static_assert(u64(HaltReason::BreakLoop) == u64(BreakLoop));
+2 -43
View File
@@ -295,10 +295,6 @@ struct System::Impl {
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) { SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) {
InitializeKernel(system); InitializeKernel(system);
if (params.applet_type == Service::AM::AppletType::Application) {
current_application_filepath = filepath;
}
const auto file = GetGameFileFromPath(virtual_filesystem, filepath); const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
// Create the application process // Create the application process
@@ -334,7 +330,7 @@ struct System::Impl {
LaunchTimestampCache::SaveLaunchTimestamp(params.program_id); LaunchTimestampCache::SaveLaunchTimestamp(params.program_id);
// Make the process created be the application // Make the process created be the application
kernel.SetApplicationProcess(process->GetHandle()); 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)};
@@ -471,7 +467,6 @@ struct System::Impl {
Core::SpeedLimiter speed_limiter; Core::SpeedLimiter speed_limiter;
ExecuteProgramCallback execute_program_callback; ExecuteProgramCallback execute_program_callback;
ExitCallback exit_callback; ExitCallback exit_callback;
ApplicationChangedCallback application_changed_callback;
std::optional<Service::Services> services; std::optional<Service::Services> services;
std::optional<Core::Debugger> debugger; std::optional<Core::Debugger> debugger;
@@ -493,8 +488,6 @@ struct System::Impl {
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<u8, 0x20> build_id{}; std::array<u8, 0x20> build_id{};
std::string current_application_filepath;
/// Service manager /// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager; std::shared_ptr<Service::SM::ServiceManager> service_manager;
/// ContentProviderUnion instance /// ContentProviderUnion instance
@@ -734,25 +727,7 @@ const Core::SpeedLimiter& System::SpeedLimiter() const {
} }
u64 System::GetApplicationProcessProgramID() const { u64 System::GetApplicationProcessProgramID() const {
const auto* const process = impl->kernel.ApplicationProcess(); return impl->kernel.ApplicationProcess()->GetProgramId();
return process != nullptr ? process->GetProgramId() : 0;
}
u64 System::GetProgramIdForProcessId(u64 process_id) const {
auto process = impl->kernel.GetProcessByProcessId(process_id);
return process.IsNull() ? 0 : process->GetProgramId();
}
u64 System::ResolveCallerProgramId(u64 process_id) const {
if (const auto program_id = this->GetProgramIdForProcessId(process_id); program_id != 0) {
return program_id;
}
const auto fallback = this->GetApplicationProcessProgramID();
LOG_WARNING(Core,
"Could not resolve caller process_id={}, falling back to application {:016X}",
process_id, fallback);
return fallback;
} }
Loader::ResultStatus System::GetGameName(std::string& out) const { Loader::ResultStatus System::GetGameName(std::string& out) const {
@@ -935,10 +910,6 @@ void System::ExecuteProgram(std::size_t program_index) {
} }
} }
const std::string& System::GetCurrentApplicationFilePath() const {
return impl->current_application_filepath;
}
/// @brief Gets a reference to the user channel stack. /// @brief Gets a reference to the user channel stack.
/// It is used to transfer data between programs. /// It is used to transfer data between programs.
std::vector<std::vector<u8>>& System::GetUserChannel() { std::vector<std::vector<u8>>& System::GetUserChannel() {
@@ -990,18 +961,6 @@ void System::Exit() {
} }
} }
void System::RegisterApplicationChangedCallback(ApplicationChangedCallback&& callback) {
impl->application_changed_callback = std::move(callback);
}
void System::NotifyApplicationChanged(u64 program_id) {
//LOG_DEBUG(Core, "Running application changed to {:016X}", program_id);
if (impl->application_changed_callback) {
impl->application_changed_callback(program_id);
}
}
void System::ApplySettings() { void System::ApplySettings() {
impl->RefreshTime(*this); impl->RefreshTime(*this);
-9
View File
@@ -322,10 +322,6 @@ public:
[[nodiscard]] u64 GetApplicationProcessProgramID() const; [[nodiscard]] u64 GetApplicationProcessProgramID() const;
[[nodiscard]] u64 GetProgramIdForProcessId(u64 process_id) const;
[[nodiscard]] u64 ResolveCallerProgramId(u64 process_id) const;
/// Gets the name of the current game /// Gets the name of the current game
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const; [[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
@@ -426,7 +422,6 @@ public:
void PushGeneralChannelData(std::vector<u8>&& data); void PushGeneralChannelData(std::vector<u8>&& data);
bool TryPopGeneralChannel(std::vector<u8>& out_data); bool TryPopGeneralChannel(std::vector<u8>& out_data);
[[nodiscard]] Service::Event& GetGeneralChannelEvent(); [[nodiscard]] Service::Event& GetGeneralChannelEvent();
[[nodiscard]] const std::string& GetCurrentApplicationFilePath() const;
/// Type used for the frontend to designate a callback for System to exit the application. /// Type used for the frontend to designate a callback for System to exit the application.
using ExitCallback = std::function<void()>; using ExitCallback = std::function<void()>;
@@ -440,10 +435,6 @@ public:
/// Instructs the frontend to exit the application. /// Instructs the frontend to exit the application.
void Exit(); void Exit();
using ApplicationChangedCallback = std::function<void(u64 program_id)>;
void RegisterApplicationChangedCallback(ApplicationChangedCallback&& callback);
void NotifyApplicationChanged(u64 program_id);
/// Applies any changes to settings to this core instance. /// Applies any changes to settings to this core instance.
void ApplySettings(); void ApplySettings();
-1
View File
@@ -38,7 +38,6 @@ constexpr u32 CpuClockTargetMhz(Settings::CpuClock clock) {
} }
} }
#undef CreateEvent
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
return std::make_shared<EventType>(std::move(callback), std::move(name)); return std::make_shared<EventType>(std::move(callback), std::move(name));
} }
+2 -2
View File
@@ -29,7 +29,7 @@ static u8 MasterKeyIdForKeyGeneration(u8 key_generation) {
return std::max<u8>(key_generation, 1) - 1; return std::max<u8>(key_generation, 1) - 1;
} }
NCA::NCA(VirtualFile file_, const NCA* base_nca, bool allow_missing_base) NCA::NCA(VirtualFile file_, const NCA* base_nca)
: file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { : file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
if (file == nullptr) { if (file == nullptr) {
status = Loader::ResultStatus::ErrorNullFile; status = Loader::ResultStatus::ErrorNullFile;
@@ -110,7 +110,7 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca, bool allow_missing_base)
} }
} }
if (is_update && base_nca == nullptr && !allow_missing_base) { if (is_update && base_nca == nullptr) {
status = Loader::ResultStatus::ErrorMissingBKTRBaseRomFS; status = Loader::ResultStatus::ErrorMissingBKTRBaseRomFS;
} else { } else {
status = Loader::ResultStatus::Success; status = Loader::ResultStatus::Success;
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -66,7 +63,7 @@ inline bool IsDirectoryLogoPartition(const VirtualDir& pfs) {
// After construction, use GetStatus to determine if the file is valid and ready to be used. // After construction, use GetStatus to determine if the file is valid and ready to be used.
class NCA : public ReadOnlyVfsDirectory { class NCA : public ReadOnlyVfsDirectory {
public: public:
explicit NCA(VirtualFile file, const NCA* base_nca = nullptr, bool allow_missing_base = false); explicit NCA(VirtualFile file, const NCA* base_nca = nullptr);
~NCA() override; ~NCA() override;
Loader::ResultStatus GetStatus() const; Loader::ResultStatus GetStatus() const;
+5 -5
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -185,13 +185,13 @@ static_assert(sizeof(SaveDataFilter) == 0x48, "SaveDataFilter has invalid size."
static_assert(std::is_trivially_copyable_v<SaveDataFilter>, static_assert(std::is_trivially_copyable_v<SaveDataFilter>,
"Data type must be trivially copyable."); "Data type must be trivially copyable.");
struct SaveDataHashSalt { struct HashSalt {
static constexpr size_t Size = 32; static constexpr size_t Size = 32;
std::array<u8, Size> value; std::array<u8, Size> value;
}; };
static_assert(std::is_trivially_copyable_v<SaveDataHashSalt>, "Data type must be trivially copyable."); static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(SaveDataHashSalt) == SaveDataHashSalt::Size); static_assert(sizeof(HashSalt) == HashSalt::Size);
struct SaveDataCreationInfo2 { struct SaveDataCreationInfo2 {
@@ -210,7 +210,7 @@ struct SaveDataCreationInfo2 {
u8 reserved1; u8 reserved1;
bool is_hash_salt_enabled; bool is_hash_salt_enabled;
u8 reserved2; u8 reserved2;
SaveDataHashSalt hash_salt; HashSalt hash_salt;
SaveDataMetaType meta_type; SaveDataMetaType meta_type;
u8 reserved3; u8 reserved3;
s32 meta_size; s32 meta_size;
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -14,7 +11,7 @@
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_vector.h" #include "core/file_sys/vfs/vfs_vector.h"
namespace FileSys::RomFSBuilder { namespace FileSys {
constexpr u64 FS_MAX_PATH = 0x301; constexpr u64 FS_MAX_PATH = 0x301;
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,7 +9,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
namespace FileSys::RomFSBuilder { namespace FileSys {
struct RomFSBuildDirectoryContext; struct RomFSBuildDirectoryContext;
struct RomFSBuildFileContext; struct RomFSBuildFileContext;
@@ -4,7 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_indirect_storage.h" #include "core/file_sys/fssystem/fssystem_indirect_storage.h"
@@ -100,18 +99,6 @@ Result IndirectStorage::GetEntryList(Entry* out_entries, s32* out_entry_count, s
R_SUCCEED(); R_SUCCEED();
} }
void IndirectStorage::ReportMissingOriginal(s64 offset, s64 size) {
if (m_reported_missing_original) {
return;
}
m_reported_missing_original = true;
LOG_ERROR(Common_Filesystem,
"Patch storage requests {:#x} bytes at {:#x} from a base storage that is not "
"present; this data will read as garbage",
size, offset);
}
size_t IndirectStorage::Read(u8* buffer, size_t size, size_t offset) const { size_t IndirectStorage::Read(u8* buffer, size_t size, size_t offset) const {
// Validate pre-conditions. // Validate pre-conditions.
ASSERT(this->IsInitialized()); ASSERT(this->IsInitialized());
@@ -85,9 +85,6 @@ public:
void SetStorage(s32 idx, VirtualFile storage) { void SetStorage(s32 idx, VirtualFile storage) {
ASSERT(0 <= idx && idx < StorageCount); ASSERT(0 <= idx && idx < StorageCount);
m_data_storage[idx] = storage; m_data_storage[idx] = storage;
if (idx == 0) {
m_original_missing = storage == nullptr || storage->GetSize() == 0;
}
} }
template <typename T> template <typename T>
@@ -133,9 +130,6 @@ protected:
template <bool ContinuousCheck, bool RangeCheck, typename F> template <bool ContinuousCheck, bool RangeCheck, typename F>
Result OperatePerEntry(s64 offset, s64 size, F func); Result OperatePerEntry(s64 offset, s64 size, F func);
// Launching another game makes the original storage inaccessable.
// This is a helper for multi-nca games.
void ReportMissingOriginal(s64 offset, s64 size);
private: private:
struct ContinuousReadingEntry { struct ContinuousReadingEntry {
@@ -160,8 +154,6 @@ private:
private: private:
mutable BucketTree m_table; mutable BucketTree m_table;
std::array<VirtualFile, StorageCount> m_data_storage; std::array<VirtualFile, StorageCount> m_data_storage;
bool m_original_missing{false};
bool m_reported_missing_original{false};
}; };
template <bool ContinuousCheck, bool RangeCheck, typename F> template <bool ContinuousCheck, bool RangeCheck, typename F>
@@ -280,10 +272,6 @@ Result IndirectStorage::OperatePerEntry(s64 offset, s64 size, F func) {
if (needs_operate) { if (needs_operate) {
const auto cur_entry_phys_offset = cur_entry.GetPhysicalOffset(); const auto cur_entry_phys_offset = cur_entry.GetPhysicalOffset();
if (cur_entry.storage_index == 0 && m_original_missing) {
this->ReportMissingOriginal(cur_offset, cur_size);
}
if constexpr (RangeCheck) { if constexpr (RangeCheck) {
// Get the current data storage's size. // Get the current data storage's size.
s64 cur_data_storage_size = m_data_storage[cur_entry.storage_index]->GetSize(); s64 cur_data_storage_size = m_data_storage[cur_entry.storage_index]->GetSize();
+2 -2
View File
@@ -48,11 +48,11 @@ struct ContentRecord {
std::array<u8, 0x10> nca_id; std::array<u8, 0x10> nca_id;
std::array<u8, 0x6> size; std::array<u8, 0x6> size;
ContentRecordType type; ContentRecordType type;
u8 id_offset; INSERT_PADDING_BYTES(1);
}; };
static_assert(sizeof(ContentRecord) == 0x38, "ContentRecord has incorrect size."); static_assert(sizeof(ContentRecord) == 0x38, "ContentRecord has incorrect size.");
constexpr ContentRecord EMPTY_META_CONTENT_RECORD{{}, {}, {}, ContentRecordType::Meta, 0}; constexpr ContentRecord EMPTY_META_CONTENT_RECORD{{}, {}, {}, ContentRecordType::Meta, {}};
struct MetaRecord { struct MetaRecord {
u64_le title_id; u64_le title_id;
+5 -30
View File
@@ -567,45 +567,20 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
} }
static std::optional<NcaID> CheckMapForContentRecord(const ankerl::unordered_dense::map<u64, CNMT>& map, u64 title_id, ContentRecordType type) { static std::optional<NcaID> CheckMapForContentRecord(const ankerl::unordered_dense::map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
auto cmnt_iter = map.find(title_id); const auto cmnt_iter = map.find(title_id);
u8 id_offset = 0;
if (cmnt_iter == map.cend()) { if (cmnt_iter == map.cend()) {
const auto program_index = title_id & AOC_TITLE_ID_MASK; return std::nullopt;
if (program_index == 0) {
return std::nullopt;
}
cmnt_iter = map.find(title_id & ~AOC_TITLE_ID_MASK);
if (cmnt_iter == map.cend()) {
return std::nullopt;
}
id_offset = static_cast<u8>(program_index);
} }
const auto& cnmt = cmnt_iter->second; const auto& cnmt = cmnt_iter->second;
const auto& content_records = cnmt.GetContentRecords(); const auto& content_records = cnmt.GetContentRecords();
const auto iter = std::find_if(content_records.cbegin(), content_records.cend(), const auto iter = std::find_if(content_records.cbegin(), content_records.cend(),
[type, id_offset](const ContentRecord& rec) { [type](const ContentRecord& rec) { return rec.type == type; });
return rec.type == type && rec.id_offset == id_offset; if (iter == content_records.cend()) {
});
if (iter != content_records.cend()) {
return std::make_optional(iter->nca_id);
}
if (id_offset != 0) {
return std::nullopt; return std::nullopt;
} }
const auto fallback_iter = return std::make_optional(iter->nca_id);
std::find_if(content_records.cbegin(), content_records.cend(),
[type](const ContentRecord& rec) { return rec.type == type; });
if (fallback_iter == content_records.cend()) {
return std::nullopt;
}
return std::make_optional(fallback_iter->nca_id);
} }
std::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id, std::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
+10 -10
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -38,7 +38,7 @@ struct RomFSHeader {
}; };
static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
struct RomFSDirectoryEntry { struct DirectoryEntry {
u32_le parent; u32_le parent;
u32_le sibling; u32_le sibling;
u32_le child_dir; u32_le child_dir;
@@ -46,9 +46,9 @@ struct RomFSDirectoryEntry {
u32_le hash; u32_le hash;
u32_le name_length; u32_le name_length;
}; };
static_assert(sizeof(RomFSDirectoryEntry) == 0x18, "RomFSDirectoryEntry has incorrect size."); static_assert(sizeof(DirectoryEntry) == 0x18, "DirectoryEntry has incorrect size.");
struct RomFSFileEntry { struct FileEntry {
u32_le parent; u32_le parent;
u32_le sibling; u32_le sibling;
u64_le offset; u64_le offset;
@@ -56,7 +56,7 @@ struct RomFSFileEntry {
u32_le hash; u32_le hash;
u32_le name_length; u32_le name_length;
}; };
static_assert(sizeof(RomFSFileEntry) == 0x20, "RomFSFileEntry has incorrect size."); static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
struct RomFSTraversalContext { struct RomFSTraversalContext {
RomFSHeader header; RomFSHeader header;
@@ -84,14 +84,14 @@ std::pair<EntryType, std::string> GetEntry(const RomFSTraversalContext& ctx, siz
return {entry, std::move(name)}; return {entry, std::move(name)};
} }
std::pair<RomFSDirectoryEntry, std::string> GetDirectoryEntry(const RomFSTraversalContext& ctx, std::pair<DirectoryEntry, std::string> GetDirectoryEntry(const RomFSTraversalContext& ctx,
size_t directory_offset) { size_t directory_offset) {
return GetEntry<RomFSDirectoryEntry, &RomFSTraversalContext::directory_meta>(ctx, directory_offset); return GetEntry<DirectoryEntry, &RomFSTraversalContext::directory_meta>(ctx, directory_offset);
} }
std::pair<RomFSFileEntry, std::string> GetFileEntry(const RomFSTraversalContext& ctx, std::pair<FileEntry, std::string> GetFileEntry(const RomFSTraversalContext& ctx,
size_t file_offset) { size_t file_offset) {
return GetEntry<RomFSFileEntry, &RomFSTraversalContext::file_meta>(ctx, file_offset); return GetEntry<FileEntry, &RomFSTraversalContext::file_meta>(ctx, file_offset);
} }
void ProcessFile(const RomFSTraversalContext& ctx, u32 this_file_offset, void ProcessFile(const RomFSTraversalContext& ctx, u32 this_file_offset,
@@ -163,7 +163,7 @@ VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
if (dir == nullptr) if (dir == nullptr)
return nullptr; return nullptr;
RomFSBuilder::RomFSBuildContext ctx{dir, ext}; RomFSBuildContext ctx{dir, ext};
return ConcatenatedVfsFile::MakeConcatenatedFile(0, dir->GetName(), ctx.Build()); return ConcatenatedVfsFile::MakeConcatenatedFile(0, dir->GetName(), ctx.Build());
} }
+6 -8
View File
@@ -12,7 +12,6 @@
#include "common/hex_util.h" #include "common/hex_util.h"
#include "common/logging.h" #include "common/logging.h"
#include "core/crypto/key_manager.h" #include "core/crypto/key_manager.h"
#include "core/file_sys/common_funcs.h"
#include "core/file_sys/content_archive.h" #include "core/file_sys/content_archive.h"
#include "core/file_sys/nca_metadata.h" #include "core/file_sys/nca_metadata.h"
#include "core/file_sys/partition_filesystem.h" #include "core/file_sys/partition_filesystem.h"
@@ -66,12 +65,10 @@ u64 NSP::GetProgramTitleID() const {
} }
auto program_id = expected_program_id; auto program_id = expected_program_id;
if (program_id == 0 && !program_status.empty()) { if (program_id == 0) {
program_id = std::min_element(program_status.cbegin(), program_status.cend(), if (!program_status.empty()) {
[](const auto& lhs, const auto& rhs) { program_id = program_status.begin()->first;
return lhs.first < rhs.first; }
})
->first;
} }
program_id = program_id + program_index; program_id = program_id + program_index;
@@ -276,7 +273,8 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
// If the last 3 hexadecimal digits of the NCA's TitleID is between 0x1 and // If the last 3 hexadecimal digits of the NCA's TitleID is between 0x1 and
// 0x7FF, this is a multi-program update NCA. Otherwise, this is a regular // 0x7FF, this is a multi-program update NCA. Otherwise, this is a regular
// update NCA. // update NCA.
if ((next_nca->GetTitleId() & AOC_TITLE_ID_MASK) != 0) { if ((next_nca->GetTitleId() & 0x7FF) != 0 &&
(next_nca->GetTitleId() & 0x800) == 0) {
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] = ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] =
std::move(next_nca); std::move(next_nca);
} else { } else {
+1 -7
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -10,12 +10,6 @@
#include "common/fs/path_util.h" #include "common/fs/path_util.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
#undef CopyFile
#undef MoveFile
namespace FileSys { namespace FileSys {
VfsFilesystem::VfsFilesystem(VirtualDir root_) : root(std::move(root_)) {} VfsFilesystem::VfsFilesystem(VirtualDir root_) : root(std::move(root_)) {}
+1 -5
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -99,10 +99,6 @@ private:
std::string name; std::string name;
}; };
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
// An implementation of VfsDirectory that maintains two vectors for subdirectories and files. // An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
// Vector data is supplied upon construction. // Vector data is supplied upon construction.
class VectorVfsDirectory : public VfsDirectory { class VectorVfsDirectory : public VfsDirectory {
+4 -21
View File
@@ -349,18 +349,9 @@ struct KernelCore::Impl {
object_name_global_data.emplace(kernel); object_name_global_data.emplace(kernel);
} }
void SetApplicationProcess(KernelCore& kernel, KProcess* process) { void MakeApplicationProcess(KernelCore& kernel, KProcess* process) {
if (application_process == process)
return;
KProcess* const previous = application_process;
application_process = process; application_process = process;
application_process->Open(kernel);
if (application_process != nullptr)
application_process->Open(kernel);
if (previous != nullptr)
previous->Close(kernel);
} }
/// Sets the host thread ID for the caller. /// Sets the host thread ID for the caller.
@@ -888,8 +879,8 @@ void KernelCore::RemoveProcess(KProcess* process) {
} }
} }
void KernelCore::SetApplicationProcess(KProcess* process) { void KernelCore::MakeApplicationProcess(KProcess* process) {
impl->SetApplicationProcess(*this, process); impl->MakeApplicationProcess(*this, process);
} }
KProcess* KernelCore::ApplicationProcess() { KProcess* KernelCore::ApplicationProcess() {
@@ -900,14 +891,6 @@ const KProcess* KernelCore::ApplicationProcess() const {
return impl->application_process; return impl->application_process;
} }
KScopedAutoObject<KProcess> KernelCore::GetProcessByProcessId(u64 process_id) {
std::scoped_lock lk{impl->process_list_lock};
for (auto* const process : impl->process_list)
if (process != nullptr && process->GetProcessId() == process_id)
return {*this, process};
return {*this, nullptr};
}
std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() { std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
std::list<KScopedAutoObject<KProcess>> processes; std::list<KScopedAutoObject<KProcess>> processes;
std::scoped_lock lk{impl->process_list_lock}; std::scoped_lock lk{impl->process_list_lock};
+2 -5
View File
@@ -124,8 +124,8 @@ public:
void AppendNewProcess(KProcess* process); void AppendNewProcess(KProcess* process);
void RemoveProcess(KProcess* process); void RemoveProcess(KProcess* process);
/// Makes the given process the current application process. /// Makes the given process the new application process.
void SetApplicationProcess(KProcess* process); void MakeApplicationProcess(KProcess* process);
/// Retrieves a pointer to the application process. /// Retrieves a pointer to the application process.
KProcess* ApplicationProcess(); KProcess* ApplicationProcess();
@@ -133,9 +133,6 @@ public:
/// Retrieves a const pointer to the application process. /// Retrieves a const pointer to the application process.
const KProcess* ApplicationProcess() const; const KProcess* ApplicationProcess() const;
/// Retrieves the process with the given process ID, or a null object.
KScopedAutoObject<KProcess> GetProcessByProcessId(u64 process_id);
/// Retrieves the list of processes. /// Retrieves the list of processes.
std::list<KScopedAutoObject<KProcess>> GetProcessList(); std::list<KScopedAutoObject<KProcess>> GetProcessList();
+1 -5
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-late // SPDX-License-Identifier: GPL-2.0-or-late
@@ -13,10 +13,6 @@
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc.h"
#undef OutputDebugString
#undef GetObject
#undef CreateProcess
namespace Kernel::Svc { namespace Kernel::Svc {
static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) { static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) {
+10 -10
View File
@@ -11,11 +11,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
namespace { namespace {
[[nodiscard]] inline constexpr bool IsValidSetAddressRange(u64 address, u64 size) { constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
return address + size > address;
}
[[nodiscard]] inline constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
switch (perm) { switch (perm) {
case MemoryPermission::None: case MemoryPermission::None:
case MemoryPermission::Read: case MemoryPermission::Read:
@@ -26,6 +22,13 @@ namespace {
} }
} }
// Checks if address + size is greater than the given address
// This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero.
constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address;
}
// Helper function that performs the common sanity checks for svcMapMemory // Helper function that performs the common sanity checks for svcMapMemory
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing // and svcUnmapMemory. This is doable, as both functions perform their sanitizing
// in the same order. // in the same order.
@@ -50,17 +53,14 @@ Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr
R_THROW(ResultInvalidSize); R_THROW(ResultInvalidSize);
} }
// Checks if address + size is greater than the given address if (!IsValidAddressRange(dst_addr, size)) {
// This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero.
if (!IsValidSetAddressRange(dst_addr, size)) {
LOG_ERROR(Kernel_SVC, LOG_ERROR(Kernel_SVC,
"Destination is not a valid address range, addr={:#016x}, size={:#016x}", "Destination is not a valid address range, addr={:#016x}, size={:#016x}",
dst_addr, size); dst_addr, size);
R_THROW(ResultInvalidCurrentMemory); R_THROW(ResultInvalidCurrentMemory);
} }
if (!IsValidSetAddressRange(src_addr, size)) { if (!IsValidAddressRange(src_addr, size)) {
LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr={:#016x}, size={:#016x}", LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr={:#016x}, size={:#016x}",
src_addr, size); src_addr, size);
R_THROW(ResultInvalidCurrentMemory); R_THROW(ResultInvalidCurrentMemory);
@@ -11,11 +11,11 @@
namespace Kernel::Svc { namespace Kernel::Svc {
namespace { namespace {
[[nodiscard]] inline constexpr bool IsValidAddressRange(u64 address, u64 size) { constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address; return address + size > address;
} }
[[nodiscard]] inline constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
switch (perm) { switch (perm) {
case Svc::MemoryPermission::None: case Svc::MemoryPermission::None:
case Svc::MemoryPermission::Read: case Svc::MemoryPermission::Read:
-4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// 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
@@ -13,7 +10,6 @@ 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 ResultLibraryAppletTerminated{ErrorModule::AM, 22};
constexpr Result ResultApplicationRecordNotFound{ErrorModule::AM, 37};
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};
+1 -9
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -201,14 +201,6 @@ enum class ProgramSpecifyKind : u32 {
RestartProgram = 2, RestartProgram = 2,
}; };
// Maufeat: Use enums for zindex instead of using random zindex numbers
enum AppletZIndex : s32 {
Background = 0,
Foreground = 1,
ForegroundVisible = 2,
Overlay = 3,
};
struct CommonArguments { struct CommonArguments {
CommonArgumentVersion arguments_version; CommonArgumentVersion arguments_version;
CommonArgumentSize size; CommonArgumentSize size;
+9 -9
View File
@@ -56,22 +56,22 @@ void Applet::UpdateSuspensionStateLocked(bool force_message) {
} }
} }
void Applet::SetInteractibleLocked(bool pad_interactible, bool touch_interactible) { void Applet::SetInteractibleLocked(bool interactible) {
if (is_pad_interactible == pad_interactible && is_touch_interactible == touch_interactible) { if (is_interactible == interactible) {
return; return;
} }
is_pad_interactible = pad_interactible; is_interactible = interactible;
is_touch_interactible = touch_interactible;
const bool exit_requested = lifecycle_manager.GetExitRequested(); const bool exit_requested = lifecycle_manager.GetExitRequested();
const bool pad_enabled = pad_interactible && !exit_requested; const bool input_enabled = interactible && !exit_requested;
const bool touch_enabled = touch_interactible && !exit_requested;
LOG_DEBUG(Service_AM, "applet={} pad={} touch={} exit_requested={}", if (applet_id == AppletId::OverlayDisplay || applet_id == AppletId::Application) {
static_cast<u32>(applet_id), pad_enabled, touch_enabled, exit_requested); LOG_DEBUG(Service_AM, "called, applet={} interactible={} exit_requested={} input_enabled={} overlay_in_foreground={}",
static_cast<u32>(applet_id), interactible, exit_requested, input_enabled, overlay_in_foreground);
}
hid_registration.EnableAppletToGetInput(pad_enabled, touch_enabled); hid_registration.EnableAppletToGetInput(input_enabled);
} }
void Applet::OnProcessTerminatedLocked() { void Applet::OnProcessTerminatedLocked() {
+3 -5
View File
@@ -125,11 +125,9 @@ struct Applet {
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_activity_runnable{};
bool is_pad_interactible{true}; bool is_interactible{true};
bool is_touch_interactible{true};
bool window_visible{true}; bool window_visible{true};
bool overlay_watching_short_home_button{false}; bool overlay_in_foreground{false};
bool overlay_handling_touch_input{false};
// Events // Events
Event overlay_event; Event overlay_event;
@@ -150,7 +148,7 @@ struct Applet {
// Process state management // Process state management
void UpdateSuspensionStateLocked(bool force_message); void UpdateSuspensionStateLocked(bool force_message);
void SetInteractibleLocked(bool pad_interactible, bool touch_interactible); void SetInteractibleLocked(bool interactible);
void OnProcessTerminatedLocked(); void OnProcessTerminatedLocked();
}; };
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -6,7 +6,6 @@
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/am/display_layer_manager.h" #include "core/hle/service/am/display_layer_manager.h"
#include "core/hle/service/nvnflinger/hwc_layer.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/application_display_service.h" #include "core/hle/service/vi/application_display_service.h"
#include "core/hle/service/vi/container.h" #include "core/hle/service/vi/container.h"
@@ -34,7 +33,6 @@ void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* pro
m_system_shared_buffer_id = 0; m_system_shared_buffer_id = 0;
m_system_shared_layer_id = 0; m_system_shared_layer_id = 0;
m_applet_id = applet_id; m_applet_id = applet_id;
m_library_applet_mode = mode;
m_buffer_sharing_enabled = false; m_buffer_sharing_enabled = false;
m_blending_enabled = mode == LibraryAppletMode::PartialForeground || m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
mode == LibraryAppletMode::PartialForegroundIndirectDisplay; mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
@@ -74,16 +72,14 @@ Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()})); out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id); m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id);
(void)m_display_service->GetContainer()->SetLayerStackMask(*out_layer_id,
this->GetLayerStackMask());
if (m_applet_id != AppletId::Application) { if (m_applet_id != AppletId::Application) {
(void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id); (void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id);
if (m_applet_id == AppletId::OverlayDisplay) { if (m_applet_id == AppletId::OverlayDisplay) {
(void)m_manager_display_service->SetLayerZIndex(Overlay, *out_layer_id); (void)m_manager_display_service->SetLayerZIndex(-1, *out_layer_id);
(void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true); (void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true);
} else { } else {
(void)m_manager_display_service->SetLayerZIndex(Foreground, *out_layer_id); (void)m_manager_display_service->SetLayerZIndex(1, *out_layer_id);
} }
} }
@@ -126,12 +122,10 @@ Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
// Ensure the overlay layer is visible // Ensure the overlay layer is visible
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
(void)m_display_service->GetContainer()->SetLayerStackMask(m_system_shared_layer_id,
this->GetLayerStackMask());
m_manager_display_service->SetLayerBlending(m_blending_enabled, m_system_shared_layer_id); m_manager_display_service->SetLayerBlending(m_blending_enabled, m_system_shared_layer_id);
s32 initial_z = Foreground; s32 initial_z = 1;
if (m_applet_id == AppletId::OverlayDisplay) { if (m_applet_id == AppletId::OverlayDisplay) {
initial_z = Overlay; initial_z = -1;
(void)m_display_service->GetContainer()->SetLayerIsOverlay(m_system_shared_layer_id, true); (void)m_display_service->GetContainer()->SetLayerIsOverlay(m_system_shared_layer_id, true);
} }
m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id); m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id);
@@ -148,36 +142,6 @@ Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_bu
R_SUCCEED(); R_SUCCEED();
} }
u32 DisplayLayerManager::GetLayerStackMask() const {
using Nvnflinger::LayerStackBit;
using Nvnflinger::LayerStackId;
constexpr u32 Displayed = LayerStackBit(LayerStackId::Default);
constexpr u32 Screenshot = LayerStackBit(LayerStackId::Screenshot);
constexpr u32 Recording = LayerStackBit(LayerStackId::Recording);
constexpr u32 LastFrame = LayerStackBit(LayerStackId::LastFrame);
constexpr u32 Debug = LayerStackBit(LayerStackId::ApplicationForDebug);
switch (m_applet_id) {
case AppletId::Application:
return Displayed | Screenshot | Recording | LastFrame | Debug;
case AppletId::OverlayDisplay:
return Displayed;
case AppletId::QLaunch:
return Displayed;
default:
break;
}
switch (m_library_applet_mode) {
case LibraryAppletMode::AllForeground:
case LibraryAppletMode::AllForegroundInitiallyHidden:
return Displayed | Screenshot | LastFrame;
default:
return Displayed | Screenshot;
}
}
void DisplayLayerManager::SetWindowVisibility(bool visible) { void DisplayLayerManager::SetWindowVisibility(bool visible) {
if (m_visible == visible) { if (m_visible == visible) {
return; return;
@@ -221,17 +185,10 @@ void DisplayLayerManager::SetOverlayZIndex(s32 z_index) {
} }
Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written, Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
s32* out_fbshare_layer_index, s32* out_fbshare_layer_index) {
VI::CaptureKind kind) {
R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied); R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer( R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
out_was_written, out_fbshare_layer_index, kind)); out_was_written, out_fbshare_layer_index));
}
Result DisplayLayerManager::ClearAppletCaptureBuffer(s32 fbshare_layer_index, u32 color) {
R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->ClearAppletCaptureBuffer(
fbshare_layer_index, color));
} }
} // namespace Service::AM } // namespace Service::AM
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -23,7 +23,6 @@ class KProcess;
namespace Service::VI { namespace Service::VI {
class IApplicationDisplayService; class IApplicationDisplayService;
class IManagerDisplayService; class IManagerDisplayService;
enum class CaptureKind : u32;
} // namespace Service::VI } // namespace Service::VI
namespace Service::AM { namespace Service::AM {
@@ -49,13 +48,9 @@ public:
void SetOverlayZIndex(s32 z_index); void SetOverlayZIndex(s32 z_index);
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index, Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
VI::CaptureKind kind);
Result ClearAppletCaptureBuffer(s32 fbshare_layer_index, u32 color);
private: private:
u32 GetLayerStackMask() const;
Kernel::KProcess* m_process{}; Kernel::KProcess* m_process{};
std::shared_ptr<VI::IApplicationDisplayService> m_display_service{}; std::shared_ptr<VI::IApplicationDisplayService> m_display_service{};
std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{}; std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{};
@@ -64,7 +59,6 @@ private:
u64 m_system_shared_buffer_id{}; u64 m_system_shared_buffer_id{};
u64 m_system_shared_layer_id{}; u64 m_system_shared_layer_id{};
AppletId m_applet_id{}; AppletId m_applet_id{};
LibraryAppletMode m_library_applet_mode{};
bool m_buffer_sharing_enabled{}; bool m_buffer_sharing_enabled{};
bool m_blending_enabled{}; bool m_blending_enabled{};
bool m_visible{true}; bool m_visible{true};
+6 -11
View File
@@ -36,17 +36,12 @@ HidRegistration::~HidRegistration() {
} }
} }
void HidRegistration::EnableAppletToGetInput(bool enable_pad, bool enable_touch) { void HidRegistration::EnableAppletToGetInput(bool enable) {
if (!m_process.IsInitialized()) if (m_process.IsInitialized()) {
return; m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
enable);
const auto resource_manager = m_hid_server->GetResourceManager(); m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable);
const u64 aruid = m_process.GetProcessId(); }
resource_manager->EnablePadInput(aruid, enable_pad);
resource_manager->EnableTouchScreen(aruid, enable_touch);
resource_manager->SetAruidValidForVibration(aruid, enable_pad);
} }
} // namespace Service::AM } // namespace Service::AM
+1 -1
View File
@@ -28,7 +28,7 @@ public:
~HidRegistration(); ~HidRegistration();
void RegisterCurrentProcess(); void RegisterCurrentProcess();
void EnableAppletToGetInput(bool enable_pad, bool enable_touch); void EnableAppletToGetInput(bool enable);
private: private:
Process& m_process; Process& m_process;
@@ -4,8 +4,6 @@
// 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/core.h"
#include "core/file_sys/common_funcs.h"
#include "core/hle/service/am/applet.h" #include "core/hle/service/am/applet.h"
#include "core/hle/service/am/service/applet_common_functions.h" #include "core/hle/service/am/service/applet_common_functions.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
@@ -80,7 +78,7 @@ Result IAppletCommonFunctions::SetCpuBoostRequestPriority(s32 priority) {
Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) { Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_WARNING(Service_AM, "(STUBBED) called");
*out_application_id = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID()); *out_application_id = system.GetApplicationProcessProgramID() & ~0xFFFULL;
R_SUCCEED(); R_SUCCEED();
} }
@@ -6,10 +6,8 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#include "common/hex_util.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/uuid.h" #include "common/uuid.h"
#include "core/file_sys/common_funcs.h"
#include "core/file_sys/control_metadata.h" #include "core/file_sys/control_metadata.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"
@@ -30,27 +28,6 @@
namespace Service::AM { namespace Service::AM {
namespace {
FileSys::PatchManager::Metadata GetApplicationMetadata(Core::System& system, u64 program_id) {
auto metadata = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, program_id);
if (metadata.first != nullptr) {
return metadata;
}
const auto application_id = FileSys::GetBaseTitleID(program_id);
if (application_id == program_id) {
return metadata;
}
LOG_DEBUG(Service_AM,
"no metadata for program_id={:016X}, falling back to application_id={:016X}",
program_id, application_id);
return FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, application_id);
}
} // Anonymous namespace
IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet) IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
: ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} { : ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} {
// clang-format off // clang-format off
@@ -179,7 +156,7 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
// Default to 0 (all languages supported) // Default to 0 (all languages supported)
u32 supported_languages = 0; u32 supported_languages = 0;
const auto res = GetApplicationMetadata(system, m_applet->program_id); const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
if (res.first != nullptr) { if (res.first != nullptr) {
supported_languages = res.first->GetSupportedLanguages(); supported_languages = res.first->GetSupportedLanguages();
} }
@@ -217,7 +194,7 @@ Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) { Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
LOG_DEBUG(Service_AM, "called"); LOG_DEBUG(Service_AM, "called");
const auto res = GetApplicationMetadata(system, m_applet->program_id); const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
if (res.first != nullptr) { if (res.first != nullptr) {
const auto& version = res.first->GetVersionString(); const auto& version = res.first->GetVersionString();
std::memcpy(out_display_version->string.data(), version.data(), std::memcpy(out_display_version->string.data(), version.data(),
@@ -347,7 +324,6 @@ Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) { Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
LOG_WARNING(Service_AM, "(stubbed)"); LOG_WARNING(Service_AM, "(stubbed)");
R_UNLESS(out_pseudo_device_id, ResultUnknown);
// This should be hashed with the device specific hash // This should be hashed with the device specific hash
// for now this will do // for now this will do
@@ -454,21 +430,15 @@ Result IApplicationFunctions::ExecuteProgram(ProgramSpecifyKind kind, u64 value)
// https://switchbrew.org/wiki/Applet_Manager_services#CreateApplicationAndRequestToStart // https://switchbrew.org/wiki/Applet_Manager_services#CreateApplicationAndRequestToStart
Result IApplicationFunctions::CreateApplicationAndRequestToStart(u64 application_id) { Result IApplicationFunctions::CreateApplicationAndRequestToStart(u64 application_id) {
LOG_INFO(Service_AM, "called, application_id={:016X} current_program_id={:016X}", application_id, m_applet->program_id); LOG_INFO(Service_AM, "called, application_id={:016X}", application_id);
if (application_id == 0 || // If application_id is 0, relaunch the current application
FileSys::GetBaseTitleID(application_id) == FileSys::GetBaseTitleID(m_applet->program_id)) { const u64 target_application_id =
const auto program_index = application_id == 0 (application_id == 0) ? m_applet->program_id : application_id;
? 0
: application_id - FileSys::GetBaseTitleID(application_id);
system.GetUserChannel() = m_applet->user_channel_launch_parameter; system.GetUserChannel() = m_applet->user_channel_launch_parameter;
system.ExecuteProgram(program_index); system.ExecuteProgram(target_application_id);
R_SUCCEED(); R_SUCCEED();
}
LOG_ERROR(Service_AM, "Launching a different application ({:016X}) is not implemented!", application_id);
R_THROW(ResultUnknown);
} }
Result IApplicationFunctions::ClearUserChannel() { Result IApplicationFunctions::ClearUserChannel() {
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -8,7 +8,6 @@
#include "core/hle/service/am/applet.h" #include "core/hle/service/am/applet.h"
#include "core/hle/service/am/service/display_controller.h" #include "core/hle/service/am/service/display_controller.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/vi/shared_buffer_manager.h"
namespace Service::AM { namespace Service::AM {
@@ -72,16 +71,16 @@ Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_l
} }
Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) { Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) {
LOG_DEBUG(Service_AM, "called, unknown0={} fbshare_layer_index={} color={:#x}", unknown0, LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}",
fbshare_layer_index, color); unknown0, fbshare_layer_index, color);
R_RETURN(applet->display_layer_manager.ClearAppletCaptureBuffer(fbshare_layer_index, color)); R_SUCCEED();
} }
Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
LOG_DEBUG(Service_AM, "called"); LOG_WARNING(Service_AM, "(STUBBED) called");
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer( R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
out_was_written, out_fbshare_layer_index, VI::CaptureKind::LastForeground)); out_fbshare_layer_index));
} }
Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() { Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
@@ -91,9 +90,9 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
LOG_DEBUG(Service_AM, "called"); LOG_WARNING(Service_AM, "(STUBBED) called");
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer( R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
out_was_written, out_fbshare_layer_index, VI::CaptureKind::CallerApplet)); out_fbshare_layer_index));
} }
Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() { Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
@@ -103,9 +102,9 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
LOG_DEBUG(Service_AM, "called"); LOG_WARNING(Service_AM, "(STUBBED) called");
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer( R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
out_was_written, out_fbshare_layer_index, VI::CaptureKind::LastApplication)); out_fbshare_layer_index));
} }
Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() { Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() {
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/am/applet.h" #include "core/hle/service/am/applet.h"
@@ -22,7 +22,7 @@ namespace Service::AM {
{10, nullptr, "StartShutdownSequenceForOverlay"}, {10, nullptr, "StartShutdownSequenceForOverlay"},
{11, nullptr, "StartRebootSequenceForOverlay"}, {11, nullptr, "StartRebootSequenceForOverlay"},
{20, D<&IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"}, {20, D<&IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
{21, D<&IOverlayFunctions::SetHandlingTouchScreenInputEnabled>, "SetHandlingTouchScreenInputEnabled"}, {21, nullptr, "SetHandlingTouchScreenInputEnabled"},
{30, nullptr, "SetHealthWarningShowingState"}, {30, nullptr, "SetHealthWarningShowingState"},
{31, D<&IOverlayFunctions::IsHealthWarningRequired>, "IsHealthWarningRequired"}, {31, D<&IOverlayFunctions::IsHealthWarningRequired>, "IsHealthWarningRequired"},
{40, nullptr, "GetApplicationNintendoLogo"}, {40, nullptr, "GetApplicationNintendoLogo"},
@@ -43,12 +43,10 @@ namespace Service::AM {
Result IOverlayFunctions::BeginToWatchShortHomeButtonMessage() { Result IOverlayFunctions::BeginToWatchShortHomeButtonMessage() {
LOG_DEBUG(Service_AM, "called"); LOG_DEBUG(Service_AM, "called");
{ m_applet->overlay_in_foreground = true;
std::scoped_lock lk{m_applet->lock}; m_applet->home_button_short_pressed_blocked = false;
m_applet->overlay_watching_short_home_button = true;
}
if (auto* window_system = system.GetAppletManager().GetWindowSystem()) { if (auto *window_system = system.GetAppletManager().GetWindowSystem()) {
window_system->RequestUpdate(); window_system->RequestUpdate();
} }
@@ -58,26 +56,16 @@ namespace Service::AM {
Result IOverlayFunctions::EndToWatchShortHomeButtonMessage() { Result IOverlayFunctions::EndToWatchShortHomeButtonMessage() {
LOG_DEBUG(Service_AM, "called"); LOG_DEBUG(Service_AM, "called");
{ m_applet->overlay_in_foreground = false;
std::scoped_lock lk{m_applet->lock}; m_applet->home_button_short_pressed_blocked = false;
m_applet->overlay_watching_short_home_button = false;
}
if (auto* window_system = system.GetAppletManager().GetWindowSystem()) { if (auto *window_system = system.GetAppletManager().GetWindowSystem()) {
window_system->RequestUpdate(); window_system->RequestUpdate();
} }
R_SUCCEED(); R_SUCCEED();
} }
Result IOverlayFunctions::SetHandlingTouchScreenInputEnabled(bool enabled) {
LOG_DEBUG(Service_AM, "called, enabled={}", enabled);
std::scoped_lock lk{m_applet->lock};
m_applet->overlay_handling_touch_input = enabled;
R_SUCCEED();
}
Result IOverlayFunctions::GetApplicationIdForLogo(Out<u64> out_application_id) { Result IOverlayFunctions::GetApplicationIdForLogo(Out<u64> out_application_id) {
LOG_DEBUG(Service_AM, "called"); LOG_DEBUG(Service_AM, "called");
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#pragma once #pragma once
@@ -20,7 +20,6 @@ namespace Service::AM {
Result SetAutoSleepTimeAndDimmingTimeEnabled(bool enabled); Result SetAutoSleepTimeAndDimmingTimeEnabled(bool enabled);
Result IsHealthWarningRequired(Out<bool> is_required); Result IsHealthWarningRequired(Out<bool> is_required);
Result SetHandlingHomeButtonShortPressedEnabled(bool enabled); Result SetHandlingHomeButtonShortPressedEnabled(bool enabled);
Result SetHandlingTouchScreenInputEnabled(bool enabled);
Result Unknown70(); Result Unknown70();
private: private:
+80 -136
View File
@@ -4,11 +4,7 @@
// 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 <utility>
#include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/am/am_results.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"
@@ -36,82 +32,46 @@ void WindowSystem::RequestUpdate() {
} }
void WindowSystem::Update() { void WindowSystem::Update() {
{ std::scoped_lock lk{m_lock};
std::scoped_lock lk{m_lock};
LOG_DEBUG(Service_AM, "called, home_menu={} application={} overlay={}", LOG_DEBUG(Service_AM, "called, home_menu={} application={} overlay={}",
m_home_menu != nullptr, m_application != nullptr, m_overlay_display != nullptr); m_home_menu != nullptr, m_application != nullptr, m_overlay_display != nullptr);
// Loop through all applets and remove terminated applets. // Loop through all applets and remove terminated applets.
this->PruneTerminatedAppletsLocked(); this->PruneTerminatedAppletsLocked();
// If the home menu is being locked into the foreground, handle that. // If the home menu is being locked into the foreground, handle that.
if (!this->LockHomeMenuIntoForegroundLocked()) { if (this->LockHomeMenuIntoForegroundLocked()) {
const bool overlay_takes_input = this->DoesOverlayTakeInputLocked(); return;
this->UpdateAppletStateLocked(m_overlay_display, true, overlay_takes_input);
this->UpdateAppletStateLocked(m_home_menu, m_foreground_requested_applet == m_home_menu, overlay_takes_input);
this->UpdateAppletStateLocked(m_application, m_foreground_requested_applet == m_application, overlay_takes_input);
}
} }
this->NotifyApplicationChangedIfNeeded(); bool overlay_blocks_input = false;
if (m_overlay_display) {
std::scoped_lock lk_overlay{m_overlay_display->lock};
overlay_blocks_input = m_overlay_display->overlay_in_foreground;
}
// Recursively update each applet root.
this->UpdateAppletStateLocked(m_home_menu, m_foreground_requested_applet == m_home_menu, overlay_blocks_input);
this->UpdateAppletStateLocked(m_application, m_foreground_requested_applet == m_application, overlay_blocks_input);
this->UpdateAppletStateLocked(m_overlay_display, true, false); // overlay is always updated, never blocked
} }
void WindowSystem::TrackApplet(std::shared_ptr<Applet> applet, bool is_application) { void WindowSystem::TrackApplet(std::shared_ptr<Applet> applet, bool is_application) {
{ std::scoped_lock lk{m_lock};
std::scoped_lock lk{m_lock};
if (applet->applet_id == AppletId::QLaunch) { if (applet->applet_id == AppletId::QLaunch) {
ASSERT(m_home_menu == nullptr); ASSERT(m_home_menu == nullptr);
m_home_menu = applet.get(); m_home_menu = applet.get();
} else if (applet->applet_id == AppletId::OverlayDisplay) { } else if (applet->applet_id == AppletId::OverlayDisplay) {
m_overlay_display = applet.get(); m_overlay_display = applet.get();
} else if (is_application) { } else if (is_application) {
ASSERT(m_application == nullptr); ASSERT(m_application == nullptr);
m_application = applet.get(); m_application = applet.get();
}
this->UpdateCurrentApplicationLocked();
m_event_observer->TrackAppletProcess(*applet);
m_applets.emplace(applet->aruid.pid, std::move(applet));
} }
this->NotifyApplicationChangedIfNeeded(); m_event_observer->TrackAppletProcess(*applet);
} m_applets.emplace(applet->aruid.pid, std::move(applet));
void WindowSystem::UpdateCurrentApplicationLocked() {
const Applet* const candidate = m_application != nullptr ? m_application : m_home_menu;
if (candidate == nullptr) {
return;
}
auto* const process = candidate->process->GetHandle();
if (process == nullptr || process == m_system.Kernel().ApplicationProcess()) {
return;
}
LOG_INFO(Service_AM, "Current application is now {:016X}", candidate->program_id);
m_system.Kernel().SetApplicationProcess(process);
Settings::SetCurrentProgramID(candidate->program_id);
m_pending_application_notification = candidate->program_id;
}
void WindowSystem::NotifyApplicationChangedIfNeeded() {
std::optional<u64> program_id;
{
std::scoped_lock lk{m_lock};
program_id = std::exchange(m_pending_application_notification, std::nullopt);
}
if (!program_id.has_value()) {
return;
}
m_system.NotifyApplicationChanged(*program_id);
} }
std::shared_ptr<Applet> WindowSystem::GetByAppletResourceUserId(u64 aruid) { std::shared_ptr<Applet> WindowSystem::GetByAppletResourceUserId(u64 aruid) {
@@ -209,40 +169,18 @@ void WindowSystem::OnExitRequested() {
} }
void WindowSystem::SendButtonAppletMessageLocked(AppletMessage message) { void WindowSystem::SendButtonAppletMessageLocked(AppletMessage message) {
const auto is_blocked = [message](const Applet& applet) { if (m_home_menu) {
if (message == AppletMessage::DetectShortPressingHomeButton && std::scoped_lock lk_home{m_home_menu->lock};
applet.applet_id == AppletId::OverlayDisplay && m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message);
!applet.overlay_watching_short_home_button) { }
return true; if (m_overlay_display) {
} std::scoped_lock lk_overlay{m_overlay_display->lock};
m_overlay_display->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message);
switch (message) { }
case AppletMessage::DetectShortPressingHomeButton: if (m_application) {
return applet.home_button_short_pressed_blocked; std::scoped_lock lk_application{m_application->lock};
case AppletMessage::DetectLongPressingHomeButton: m_application->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message);
return applet.home_button_long_pressed_blocked; }
default:
return false;
}
};
const auto send_to = [&](Applet* applet) {
if (!applet) {
return;
}
std::scoped_lock lk{applet->lock};
if (is_blocked(*applet)) {
LOG_DEBUG(Service_AM, "Applet {} is blocking message {}",
static_cast<u32>(applet->applet_id), static_cast<u32>(message));
return;
}
applet->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message);
};
send_to(m_home_menu);
send_to(m_overlay_display);
send_to(m_application);
if (m_event_observer) { if (m_event_observer) {
m_event_observer->RequestUpdate(); m_event_observer->RequestUpdate();
} }
@@ -254,9 +192,19 @@ void WindowSystem::OnSystemButtonPress(SystemButtonType type) {
case SystemButtonType::HomeButtonShortPressing: case SystemButtonType::HomeButtonShortPressing:
SendButtonAppletMessageLocked(AppletMessage::DetectShortPressingHomeButton); SendButtonAppletMessageLocked(AppletMessage::DetectShortPressingHomeButton);
break; break;
case SystemButtonType::HomeButtonLongPressing: case SystemButtonType::HomeButtonLongPressing: {
// Toggle overlay foreground visibility on long home press
if (m_overlay_display) {
std::scoped_lock lk_overlay{m_overlay_display->lock};
m_overlay_display->overlay_in_foreground = !m_overlay_display->overlay_in_foreground;
LOG_INFO(Service_AM, "Overlay long-press toggle: overlay_in_foreground={} window_visible={}", m_overlay_display->overlay_in_foreground, m_overlay_display->window_visible);
}
SendButtonAppletMessageLocked(AppletMessage::DetectLongPressingHomeButton); SendButtonAppletMessageLocked(AppletMessage::DetectLongPressingHomeButton);
break; // Force a state update after toggling overlay
if (m_event_observer) {
m_event_observer->RequestUpdate();
}
break; }
case SystemButtonType::CaptureButtonShortPressing: case SystemButtonType::CaptureButtonShortPressing:
SendButtonAppletMessageLocked(AppletMessage::DetectShortPressingCaptureButton); SendButtonAppletMessageLocked(AppletMessage::DetectShortPressingCaptureButton);
break; break;
@@ -369,8 +317,6 @@ void WindowSystem::PruneTerminatedAppletsLocked() {
m_overlay_display = nullptr; m_overlay_display = nullptr;
} }
this->UpdateCurrentApplicationLocked();
// Finalize applet. // Finalize applet.
applet->OnProcessTerminatedLocked(); applet->OnProcessTerminatedLocked();
@@ -443,20 +389,7 @@ void WindowSystem::TerminateChildAppletsLocked(Applet* applet) {
applet->lock.lock(); applet->lock.lock();
} }
bool WindowSystem::IsOverlayOpenLocked(const Applet& overlay) const { void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, bool overlay_blocking) {
return overlay.window_visible && overlay.overlay_watching_short_home_button;
}
bool WindowSystem::DoesOverlayTakeInputLocked() const {
if (m_overlay_display == nullptr) {
return false;
}
std::scoped_lock lk{m_overlay_display->lock};
return this->IsOverlayOpenLocked(*m_overlay_display);
}
void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, bool overlay_takes_input) {
// With no applet, we don't have anything to do. // With no applet, we don't have anything to do.
if (!applet) { if (!applet) {
return; return;
@@ -487,18 +420,24 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b
return false; return false;
}(); }();
const bool is_overlay = applet->applet_id == AppletId::OverlayDisplay;
// Update visibility state. // Update visibility state.
const bool should_be_visible = // Overlay applets should always be visible when window_visible is true, regardless of foreground state
is_overlay ? applet->window_visible : (is_foreground && applet->window_visible); const bool should_be_visible = (applet->applet_id == AppletId::OverlayDisplay)
? applet->window_visible
: (is_foreground && applet->window_visible);
applet->display_layer_manager.SetWindowVisibility(should_be_visible); applet->display_layer_manager.SetWindowVisibility(should_be_visible);
const bool needs_hid_input =
is_overlay ? this->IsOverlayOpenLocked(*applet)
: (is_foreground && applet->window_visible && !overlay_takes_input);
applet->SetInteractibleLocked(needs_hid_input, needs_hid_input); const bool should_be_interactible = (applet->applet_id == AppletId::OverlayDisplay)
? applet->overlay_in_foreground
: (is_foreground && applet->window_visible && !overlay_blocking);
if (applet->applet_id == AppletId::OverlayDisplay || applet->applet_id == AppletId::Application) {
LOG_DEBUG(Service_AM, "UpdateAppletStateLocked: applet={} overlay_in_foreground={} is_foreground={} window_visible={} overlay_blocking={} should_be_interactible={}",
static_cast<u32>(applet->applet_id), applet->overlay_in_foreground, is_foreground, applet->window_visible, overlay_blocking, should_be_interactible);
}
applet->SetInteractibleLocked(should_be_interactible);
// Update focus state and suspension. // Update focus state and suspension.
const bool is_obscured = has_obscuring_child_applets || !applet->window_visible; const bool is_obscured = has_obscuring_child_applets || !applet->window_visible;
@@ -514,18 +453,23 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b
applet->UpdateSuspensionStateLocked(true); applet->UpdateSuspensionStateLocked(true);
} }
// Layer ordering. Composition sorts back-to-front. Now with enums for calrity. // Z-index logic like in reference C# implementation (tuned for overlay extremes)
s32 z_index = Background; s32 z_index = 0;
if (is_overlay) { const bool now_foreground = inherited_foreground;
z_index = Overlay; if (applet->applet_id == AppletId::OverlayDisplay) {
} else if (inherited_foreground) { z_index = applet->overlay_in_foreground ? 100000 : -1;
z_index = is_obscured ? Foreground : ForegroundVisible; } else if (now_foreground && !is_obscured) {
z_index = 2;
} else if (now_foreground) {
z_index = 1;
} else {
z_index = 0;
} }
applet->display_layer_manager.SetOverlayZIndex(z_index); applet->display_layer_manager.SetOverlayZIndex(z_index);
// Recurse into child applets. // Recurse into child applets.
for (const auto& child_applet : applet->child_applets) { for (const auto& child_applet : applet->child_applets) {
this->UpdateAppletStateLocked(child_applet.get(), is_foreground, overlay_takes_input); this->UpdateAppletStateLocked(child_applet.get(), is_foreground, overlay_blocking);
} }
} }
+1 -8
View File
@@ -9,7 +9,6 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <optional>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/am/am_types.h" #include "core/hle/service/am/am_types.h"
@@ -61,16 +60,11 @@ public:
void OnPowerButtonPressed(ButtonPressDuration type) {} void OnPowerButtonPressed(ButtonPressDuration type) {}
private: private:
void UpdateCurrentApplicationLocked();
void NotifyApplicationChangedIfNeeded();
void PruneTerminatedAppletsLocked(); void PruneTerminatedAppletsLocked();
bool RestartAppletProcessLocked(Applet* applet); bool RestartAppletProcessLocked(Applet* applet);
bool LockHomeMenuIntoForegroundLocked(); bool LockHomeMenuIntoForegroundLocked();
void TerminateChildAppletsLocked(Applet* applet); void TerminateChildAppletsLocked(Applet* applet);
bool IsOverlayOpenLocked(const Applet& overlay) const; void UpdateAppletStateLocked(Applet* applet, bool is_foreground, bool overlay_blocking = false);
bool DoesOverlayTakeInputLocked() const;
void UpdateAppletStateLocked(Applet* applet, bool is_foreground, bool overlay_takes_input);
void SendButtonAppletMessageLocked(AppletMessage message); void SendButtonAppletMessageLocked(AppletMessage message);
private: private:
@@ -94,7 +88,6 @@ private:
// Applet map by aruid. // Applet map by aruid.
std::map<u64, std::shared_ptr<Applet>> m_applets{}; std::map<u64, std::shared_ptr<Applet>> m_applets{};
std::optional<u64> m_pending_application_notification{};
}; };
} // namespace Service::AM } // namespace Service::AM
@@ -23,7 +23,6 @@
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/hle/service/am/am_results.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
namespace Service::AOC { namespace Service::AOC {
@@ -32,10 +31,6 @@ static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) {
return FileSys::GetBaseTitleID(title_id) == base; return FileSys::GetBaseTitleID(title_id) == base;
} }
static u64 GetCallerBaseTitleID(Core::System& system, const ClientProcessId& process_id) {
return FileSys::GetBaseTitleID(system.ResolveCallerProgramId(*process_id));
}
static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) { static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) {
std::vector<u64> add_on_content; std::vector<u64> add_on_content;
const auto& rcu = system.GetContentProvider(); const auto& rcu = system.GetContentProvider();
@@ -96,7 +91,7 @@ IAddOnContentManager::~IAddOnContentManager() {
Result IAddOnContentManager::CountAddOnContent(Out<u32> out_count, ClientProcessId process_id) { Result IAddOnContentManager::CountAddOnContent(Out<u32> out_count, ClientProcessId process_id) {
LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid); LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid);
const auto current = GetCallerBaseTitleID(system, process_id); const auto current = system.GetApplicationProcessProgramID();
const auto& disabled = Settings::values.disabled_addons[current]; const auto& disabled = Settings::values.disabled_addons[current];
if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) { if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) {
@@ -117,7 +112,7 @@ Result IAddOnContentManager::ListAddOnContent(Out<u32> out_count,
LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
process_id.pid); process_id.pid);
const auto current = GetCallerBaseTitleID(system, process_id); const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID());
std::vector<u32> out; std::vector<u32> out;
const auto& disabled = Settings::values.disabled_addons[current]; const auto& disabled = Settings::values.disabled_addons[current];
@@ -131,7 +126,8 @@ Result IAddOnContentManager::ListAddOnContent(Out<u32> out_count,
} }
} }
R_UNLESS(out.size() >= offset, AM::ResultApplicationRecordNotFound); // TODO(DarkLordZach): Find the correct error code.
R_UNLESS(out.size() >= offset, ResultUnknown);
*out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count)); *out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count));
std::rotate(out.begin(), out.begin() + offset, out.end()); std::rotate(out.begin(), out.begin() + offset, out.end());
@@ -145,7 +141,7 @@ Result IAddOnContentManager::GetAddOnContentBaseId(Out<u64> out_title_id,
ClientProcessId process_id) { ClientProcessId process_id) {
LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid); LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid);
const auto title_id = system.ResolveCallerProgramId(*process_id); const auto title_id = system.GetApplicationProcessProgramID();
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()}; system.GetContentProvider()};
+6 -5
View File
@@ -9,12 +9,13 @@
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioIn::IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager, size_t session_id, IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioCore::AudioIn::AudioInParameter& in_params, const std::string& device_name, const AudioInParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id) Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"}, : ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<AudioCore::AudioIn::In>(system_, event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
manager, event, manager, event,
session_id)} { session_id)} {
// clang-format off // clang-format off
@@ -70,12 +71,12 @@ Result IAudioIn::Stop() {
R_RETURN(impl->StopSystem()); R_RETURN(impl->StopSystem());
} }
Result IAudioIn::AppendAudioInBuffer(InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer, Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
u64 buffer_client_ptr) { u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr)); R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
} }
Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer, Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
u64 buffer_client_ptr) { u64 buffer_client_ptr) {
if (buffer.empty()) { if (buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!"); LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// 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
@@ -10,6 +7,7 @@
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioInManager::IAudioInManager(Core::System& system_) IAudioInManager::IAudioInManager(Core::System& system_)
: ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>( : ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
@@ -36,11 +34,11 @@ Result IAudioInManager::ListAudioIns(
R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count)); R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
} }
Result IAudioInManager::OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal, Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioIn>> out_audio_in, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name, OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name, InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioIn::AudioInParameter parameter, AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) { ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
@@ -55,9 +53,9 @@ Result IAudioInManager::ListAudioInsAuto(
} }
Result IAudioInManager::OpenAudioInAuto( Result IAudioInManager::OpenAudioInAuto(
Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in, Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name, OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioCore::AudioIn::AudioInParameter parameter, InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) { InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name, R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
@@ -72,10 +70,10 @@ Result IAudioInManager::ListAudioInsAutoFiltered(
} }
Result IAudioInManager::OpenAudioInProtocolSpecified( Result IAudioInManager::OpenAudioInProtocolSpecified(
Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in, Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name, OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol, InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
AudioCore::AudioIn::AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle, AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) { ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
@@ -106,7 +104,7 @@ Result IAudioInManager::OpenAudioInProtocolSpecified(
auto& out_system = impl->sessions[new_session_id]->GetSystem(); auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal = *out_parameter_internal =
AudioCore::AudioIn::AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(), AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(), .channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()), .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())}; .state = static_cast<u32>(out_system.GetState())};
+5 -4
View File
@@ -13,9 +13,10 @@
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOut::IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, size_t session_id, IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioCore::AudioOut::AudioOutParameter& in_params, const std::string& device_name, const AudioOutParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id) Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")}, process{handle}, event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
@@ -67,12 +68,12 @@ Result IAudioOut::Stop() {
} }
Result IAudioOut::AppendAudioOutBuffer( Result IAudioOut::AppendAudioOutBuffer(
InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) { InArray<AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr)); R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr));
} }
Result IAudioOut::AppendAudioOutBufferAuto( Result IAudioOut::AppendAudioOutBufferAuto(
InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) { InArray<AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) {
if (audio_out_buffer.empty()) { if (audio_out_buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!"); LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
R_THROW(Audio::ResultInsufficientBuffer); R_THROW(Audio::ResultInsufficientBuffer);
@@ -11,6 +11,7 @@
#include "core/memory.h" #include "core/memory.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOutManager::IAudioOutManager(Core::System& system_) IAudioOutManager::IAudioOutManager(Core::System& system_)
: ServiceFramework{system_, "audout:u"} : ServiceFramework{system_, "audout:u"}
@@ -35,11 +36,11 @@ Result IAudioOutManager::ListAudioOuts(
R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count)); R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count));
} }
Result IAudioOutManager::OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal, Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out, Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name, OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name, InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioOut::AudioOutParameter parameter, AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) { ClientAppletResourceUserId aruid) {
R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name, R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
@@ -61,10 +62,10 @@ Result IAudioOutManager::ListAudioOutsAuto(
} }
Result IAudioOutManager::OpenAudioOutAuto( Result IAudioOutManager::OpenAudioOutAuto(
Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal, Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out, Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name, OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioCore::AudioOut::AudioOutParameter parameter, InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) { InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
if (!process_handle) { if (!process_handle) {
LOG_ERROR(Service_Audio, "Failed to get process handle"); LOG_ERROR(Service_Audio, "Failed to get process handle");
@@ -94,7 +95,7 @@ Result IAudioOutManager::OpenAudioOutAuto(
auto& out_system = impl->sessions[new_session_id]->GetSystem(); auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal = *out_parameter_internal =
AudioCore::AudioOut::AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(), AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(), .channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()), .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())}; .state = static_cast<u32>(out_system.GetState())};
@@ -4,20 +4,21 @@
// 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 "audio_core/renderer/audio_renderer.h"
#include "core/hle/service/audio/audio_renderer.h" #include "core/hle/service/audio/audio_renderer.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::Renderer;
IAudioRenderer::IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_, IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
AudioCore::AudioRendererParameterInternal& params, AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
Kernel::KProcess* process_handle_, u64 applet_resource_user_id, Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
s32 session_id) s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<AudioCore::Renderer::Renderer>(system_, manager, rendered_event)}, process_handle{process_handle_} { impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process_handle{
process_handle_} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"}, {0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
+7 -5
View File
@@ -24,8 +24,8 @@ static u64 GetCurrentBuildID(const Core::System::CurrentBuildProcessID& id) {
return out; return out;
} }
IBcatService::IBcatService(Core::System& system_, BcatBackend& backend_, u64 program_id_) IBcatService::IBcatService(Core::System& system_, BcatBackend& backend_)
: ServiceFramework{system_, "IBcatService"}, backend{backend_}, program_id{program_id_}, : ServiceFramework{system_, "IBcatService"}, backend{backend_},
progress{{ progress{{
ProgressServiceBackend{system_, "Normal"}, ProgressServiceBackend{system_, "Normal"},
ProgressServiceBackend{system_, "Directory"}, ProgressServiceBackend{system_, "Directory"},
@@ -70,7 +70,8 @@ Result IBcatService::RequestSyncDeliveryCache(
LOG_DEBUG(Service_BCAT, "called"); LOG_DEBUG(Service_BCAT, "called");
auto& progress_backend{GetProgressBackend(SyncType::Normal)}; auto& progress_backend{GetProgressBackend(SyncType::Normal)};
backend.Synchronize(system.Kernel(), {program_id, GetCurrentBuildID(system.GetApplicationProcessBuildID())}, backend.Synchronize(system.Kernel(), {system.GetApplicationProcessProgramID(),
GetCurrentBuildID(system.GetApplicationProcessBuildID())},
GetProgressBackend(SyncType::Normal)); GetProgressBackend(SyncType::Normal));
*out_interface = std::make_shared<IDeliveryCacheProgressService>( *out_interface = std::make_shared<IDeliveryCacheProgressService>(
@@ -85,8 +86,9 @@ Result IBcatService::RequestSyncDeliveryCacheWithDirectoryName(
LOG_DEBUG(Service_BCAT, "called, name={}", name); LOG_DEBUG(Service_BCAT, "called, name={}", name);
auto& progress_backend{GetProgressBackend(SyncType::Directory)}; auto& progress_backend{GetProgressBackend(SyncType::Directory)};
backend.SynchronizeDirectory(system.Kernel(), {program_id, GetCurrentBuildID(system.GetApplicationProcessBuildID())}, backend.SynchronizeDirectory(system.Kernel(), {system.GetApplicationProcessProgramID(),
name, progress_backend); GetCurrentBuildID(system.GetApplicationProcessBuildID())},
name, progress_backend);
*out_interface = std::make_shared<IDeliveryCacheProgressService>( *out_interface = std::make_shared<IDeliveryCacheProgressService>(
system, progress_backend.GetEvent(), progress_backend.GetImpl()); system, progress_backend.GetEvent(), progress_backend.GetImpl());
+1 -5
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
@@ -22,7 +19,7 @@ class IDeliveryCacheProgressService;
class IBcatService final : public ServiceFramework<IBcatService> { class IBcatService final : public ServiceFramework<IBcatService> {
public: public:
explicit IBcatService(Core::System& system_, BcatBackend& backend_, u64 program_id_); explicit IBcatService(Core::System& system_, BcatBackend& backend_);
~IBcatService() override; ~IBcatService() override;
private: private:
@@ -42,7 +39,6 @@ private:
const ProgressServiceBackend& GetProgressBackend(SyncType type) const; const ProgressServiceBackend& GetProgressBackend(SyncType type) const;
BcatBackend& backend; BcatBackend& backend;
u64 program_id;
std::array<ProgressServiceBackend, static_cast<size_t>(SyncType::Count)> progress; std::array<ProgressServiceBackend, static_cast<size_t>(SyncType::Count)> progress;
}; };
@@ -14,13 +14,16 @@
#include <cstring> #include <cstring>
namespace Service::News { namespace Service::News {
namespace {
[[nodiscard]] inline std::string_view ToStringViewNDS(std::span<const char> buf) { std::string_view ToStringView(std::span<const char> buf) {
const std::string_view sv{buf.data(), buf.size()}; const std::string_view sv{buf.data(), buf.size()};
const auto nul = sv.find('\0'); const auto nul = sv.find('\0');
return nul == std::string_view::npos ? sv : sv.substr(0, nul); return nul == std::string_view::npos ? sv : sv.substr(0, nul);
} }
} // namespace
INewsDataService::INewsDataService(Core::System& system_) INewsDataService::INewsDataService(Core::System& system_)
: ServiceFramework{system_, "INewsDataService"} { : ServiceFramework{system_, "INewsDataService"} {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
@@ -52,7 +55,7 @@ bool INewsDataService::TryOpen(std::string_view key, std::string_view user) {
const auto list = NewsStorage::Instance().ListAll(); const auto list = NewsStorage::Instance().ListAll();
if (!list.empty()) { if (!list.empty()) {
if (auto found = NewsStorage::Instance().FindByNewsId(ToStringViewNDS(list.front().news_id))) { if (auto found = NewsStorage::Instance().FindByNewsId(ToStringView(list.front().news_id))) {
opened_payload = std::move(found->payload); opened_payload = std::move(found->payload);
return true; return true;
} }
@@ -64,7 +67,7 @@ bool INewsDataService::TryOpen(std::string_view key, std::string_view user) {
Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) { Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) {
EnsureBuiltinNewsLoaded(); EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS({reinterpret_cast<const char*>(name.data()), name.size()}); const auto key = ToStringView({reinterpret_cast<const char*>(name.data()), name.size()});
if (TryOpen(key, {})) { if (TryOpen(key, {})) {
R_SUCCEED(); R_SUCCEED();
@@ -76,8 +79,8 @@ Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) {
Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) { Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) {
EnsureBuiltinNewsLoaded(); EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS(record.news_id); const auto key = ToStringView(record.news_id);
const auto user = ToStringViewNDS(record.user_id); const auto user = ToStringView(record.user_id);
if (TryOpen(key, user)) { if (TryOpen(key, user)) {
R_SUCCEED(); R_SUCCEED();
@@ -89,8 +92,8 @@ Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) {
Result INewsDataService::OpenWithNewsRecord(NewsRecord record) { Result INewsDataService::OpenWithNewsRecord(NewsRecord record) {
EnsureBuiltinNewsLoaded(); EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS(record.news_id); const auto key = ToStringView(record.news_id);
const auto user = ToStringViewNDS(record.user_id); const auto user = ToStringView(record.user_id);
if (TryOpen(key, user)) { if (TryOpen(key, user)) {
R_SUCCEED(); R_SUCCEED();
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -15,13 +15,13 @@
namespace Service::News { namespace Service::News {
namespace { namespace {
[[nodiscard]] inline std::string_view ToStringView(std::span<const u8> buf) { std::string_view ToStringView(std::span<const u8> buf) {
if (buf.empty()) return {}; if (buf.empty()) return {};
auto data = reinterpret_cast<const char*>(buf.data()); auto data = reinterpret_cast<const char*>(buf.data());
return {data, strnlen(data, buf.size())}; return {data, strnlen(data, buf.size())};
} }
[[nodiscard]] inline std::string_view ToStringView(std::span<const char> buf) { std::string_view ToStringView(std::span<const char> buf) {
if (buf.empty()) return {}; if (buf.empty()) return {};
return {buf.data(), strnlen(buf.data(), buf.size())}; return {buf.data(), strnlen(buf.data(), buf.size())};
} }
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
@@ -9,8 +6,6 @@
namespace Service::News { namespace Service::News {
#undef CreateEvent
IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_) IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_)
: ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_, : ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_,
"IOverwriteEventHolder"} { "IOverwriteEventHolder"} {
@@ -1,10 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/bcat/bcat_service.h" #include "core/hle/service/bcat/bcat_service.h"
#include "core/hle/service/bcat/delivery_cache_storage_service.h" #include "core/hle/service/bcat/delivery_cache_storage_service.h"
#include "core/hle/service/bcat/service_creator.h" #include "core/hle/service/bcat/service_creator.h"
@@ -41,8 +37,7 @@ IServiceCreator::~IServiceCreator() = default;
Result IServiceCreator::CreateBcatService(ClientProcessId process_id, Result IServiceCreator::CreateBcatService(ClientProcessId process_id,
OutInterface<IBcatService> out_interface) { OutInterface<IBcatService> out_interface) {
LOG_INFO(Service_BCAT, "called, process_id={}", process_id.pid); LOG_INFO(Service_BCAT, "called, process_id={}", process_id.pid);
*out_interface = *out_interface = std::make_shared<IBcatService>(system, *backend);
std::make_shared<IBcatService>(system, *backend, system.ResolveCallerProgramId(*process_id));
R_SUCCEED(); R_SUCCEED();
} }
@@ -50,7 +45,7 @@ Result IServiceCreator::CreateDeliveryCacheStorageService(
ClientProcessId process_id, OutInterface<IDeliveryCacheStorageService> out_interface) { ClientProcessId process_id, OutInterface<IDeliveryCacheStorageService> out_interface) {
LOG_INFO(Service_BCAT, "called, process_id={}", process_id.pid); LOG_INFO(Service_BCAT, "called, process_id={}", process_id.pid);
const auto title_id = system.ResolveCallerProgramId(*process_id); const auto title_id = system.GetApplicationProcessProgramID();
*out_interface = *out_interface =
std::make_shared<IDeliveryCacheStorageService>(system, fsc.GetBCATDirectory(title_id)); std::make_shared<IDeliveryCacheStorageService>(system, fsc.GetBCATDirectory(title_id));
R_SUCCEED(); R_SUCCEED();
+2 -9
View File
@@ -18,8 +18,6 @@
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#undef GetCurrentTime
namespace Service::Capture { namespace Service::Capture {
AlbumManager::AlbumManager(Core::System& system_) : system{system_} {} AlbumManager::AlbumManager(Core::System& system_) : system{system_} {}
@@ -245,15 +243,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
return SaveScreenShot(out_entry, attribute, report_option, {}, image_data, aruid); return SaveScreenShot(out_entry, attribute, report_option, {}, image_data, aruid);
} }
Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, AlbumReportOption report_option, const ApplicationData& app_data, std::span<const u8> image_data, u64 aruid) {
const ScreenShotAttribute& attribute,
AlbumReportOption report_option,
const ApplicationData& app_data, std::span<const u8> image_data,
u64 aruid) {
R_UNLESS(!image_data.empty(), ResultUnknown); //TODO: ??? R_UNLESS(!image_data.empty(), ResultUnknown); //TODO: ???
const u64 title_id = system.ResolveCallerProgramId(aruid); const u64 title_id = system.GetApplicationProcessProgramID();
auto static_service = auto static_service =
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
+1 -2
View File
@@ -95,8 +95,7 @@ void IScreenShotApplicationService::CaptureAndSaveScreenshot(AlbumReportOption r
manager->FlipVerticallyOnWrite(invert_y); manager->FlipVerticallyOnWrite(invert_y);
manager->SaveScreenShot(entry, attribute, report_option, image_data, {}); manager->SaveScreenShot(entry, attribute, report_option, image_data, {});
}, },
layout, layout);
Nvnflinger::LayerStackId::Screenshot);
} }
} // namespace Service::Capture } // namespace Service::Capture
-2
View File
@@ -19,8 +19,6 @@
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/reporter.h" #include "core/reporter.h"
#undef far
namespace Service::Fatal { namespace Service::Fatal {
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
@@ -32,10 +32,6 @@
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
namespace Service::FileSystem { namespace Service::FileSystem {
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
@@ -3,6 +3,9 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
#include <thread>
#include "common/settings.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
@@ -30,6 +33,15 @@ Result IStorage::Read(
R_UNLESS(length >= 0, FileSys::ResultInvalidSize); R_UNLESS(length >= 0, FileSys::ResultInvalidSize);
R_UNLESS(offset >= 0, FileSys::ResultInvalidOffset); R_UNLESS(offset >= 0, FileSys::ResultInvalidOffset);
static thread_local std::chrono::steady_clock::time_point last_read_tick{};
const auto now = std::chrono::steady_clock::now();
const auto period = Settings::values.debug_knobs.GetValue();
const auto ReadInterval = std::chrono::microseconds{period};
if (last_read_tick != std::chrono::steady_clock::time_point{} &&
now - last_read_tick < ReadInterval) {
std::this_thread::sleep_for(ReadInterval - (now - last_read_tick));
}
last_read_tick = std::chrono::steady_clock::now();
// Read the data from the Storage backend // Read the data from the Storage backend
backend->Read(out_bytes.data(), length, offset); backend->Read(out_bytes.data(), length, offset);
+1 -1
View File
@@ -1164,7 +1164,7 @@ Result IHidServer::InitializeSevenSixAxisSensor(ClientAppletResourceUserId aruid
GetResourceManager()->GetConsoleSixAxis()->Activate(); GetResourceManager()->GetConsoleSixAxis()->Activate();
GetResourceManager()->GetSevenSixAxis()->Activate(); GetResourceManager()->GetSevenSixAxis()->Activate();
GetResourceManager()->GetSevenSixAxis()->SetTransferMemoryAddress(t_mem_1->GetSourceAddress(), t_mem_1->GetOwner()); GetResourceManager()->GetSevenSixAxis()->SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
R_SUCCEED(); R_SUCCEED();
} }
+1 -1
View File
@@ -312,7 +312,7 @@ Result Hidbus::EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode pollin
auto& device = devices[device_index.value()].device; auto& device = devices[device_index.value()].device;
device->SetPollingMode(polling_mode); device->SetPollingMode(polling_mode);
device->SetTransferMemoryAddress(t_mem->GetSourceAddress(), t_mem->GetOwner()); device->SetTransferMemoryAddress(t_mem->GetSourceAddress());
R_SUCCEED(); R_SUCCEED();
} }
+2 -6
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -150,7 +147,7 @@ Result IRS::RunImageTransferProcessor(
MakeProcessorWithCoreContext<ImageTransferProcessor>(camera_handle, device); MakeProcessorWithCoreContext<ImageTransferProcessor>(camera_handle, device);
auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(camera_handle); auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(camera_handle);
image_transfer_processor.SetConfig(processor_config); image_transfer_processor.SetConfig(processor_config);
image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress(), t_mem->GetOwner()); image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress());
npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
Common::Input::PollingMode::IR); Common::Input::PollingMode::IR);
@@ -298,8 +295,7 @@ Result IRS::RunImageTransferExProcessor(
MakeProcessorWithCoreContext<ImageTransferProcessor>(camera_handle, device); MakeProcessorWithCoreContext<ImageTransferProcessor>(camera_handle, device);
auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(camera_handle); auto& image_transfer_processor = GetProcessor<ImageTransferProcessor>(camera_handle);
image_transfer_processor.SetConfig(processor_config); image_transfer_processor.SetConfig(processor_config);
image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress(), image_transfer_processor.SetTransferMemoryAddress(t_mem->GetSourceAddress());
t_mem->GetOwner());
npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
Common::Input::PollingMode::IR); Common::Input::PollingMode::IR);
-2
View File
@@ -27,8 +27,6 @@
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/memory.h" #include "core/memory.h"
#undef SendMessage
namespace Service { namespace Service {
SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_) SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_)
+1 -1
View File
@@ -35,7 +35,7 @@ public:
, process{kernel, process_} , process{kernel, process_}
, user_rx{std::move(user_rx_)} , user_rx{std::move(user_rx_)}
, user_ro{std::move(user_ro_)} , user_ro{std::move(user_ro_)}
, context{process_->GetMemory()} , context{system_.ApplicationMemory()}
{ {
// clang-format off // clang-format off
+1 -2
View File
@@ -212,9 +212,8 @@ struct NifmNetworkProfileData {
NifmWirelessSettingData wireless_setting_data{}; NifmWirelessSettingData wireless_setting_data{};
IpSettingData ip_setting_data{}; IpSettingData ip_setting_data{};
}; };
static_assert(sizeof(NifmNetworkProfileData) == 0x18E,
"NifmNetworkProfileData has incorrect size.");
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(NifmNetworkProfileData) == 0x18E, "NifmNetworkProfileData has incorrect size.");
struct PendingProfile { struct PendingProfile {
std::array<char, 0x21> ssid{}; std::array<char, 0x21> ssid{};
@@ -9,12 +9,15 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include "common/stb.h" #define STBI_ONLY_JPEG 1
#include <stb_image.h>
#include <stb_image_resize.h>
#include <stb_image_write.h>
#include "common/settings.h" #include "common/settings.h"
#include "core/file_sys/control_metadata.h" #include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h" #include "core/file_sys/patch_manager.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ns/language.h" #include "core/hle/service/ns/language.h"
@@ -333,8 +336,8 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestCo
constexpr s32 data_offset = 0; constexpr s32 data_offset = 0;
if (t_mem != nullptr && t_mem->GetOwner() != nullptr && app_count > 0) { if (t_mem != nullptr && app_count > 0) {
auto& memory = t_mem->GetOwner()->GetMemory(); auto& memory = system.ApplicationMemory();
const auto t_mem_address = t_mem->GetSourceAddress(); const auto t_mem_address = t_mem->GetSourceAddress();
for (size_t i = 0; i < app_count; ++i) { for (size_t i = 0; i < app_count; ++i) {
@@ -77,7 +77,6 @@ void nvdisp_disp0::Composite(std::span<const Nvnflinger::HwcLayer> sorted_layers
.transform_flags = layer.transform, .transform_flags = layer.transform,
.crop_rect = layer.crop_rect, .crop_rect = layer.crop_rect,
.blending = ConvertBlending(layer.blending), .blending = ConvertBlending(layer.blending),
.layer_stack_mask = layer.layer_stack_mask,
}); });
for (size_t i = 0; i < layer.acquire_fence.num_fences; i++) { for (size_t i = 0; i < layer.acquire_fence.num_fences; i++) {
@@ -69,7 +69,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 0x3: case 0x3:
return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output); return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output);
case 0x8: case 0x8:
return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, fd, false); return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, false);
case 0x9: case 0x9:
return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output); return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output);
case 0xb: case 0xb:
@@ -83,7 +83,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 0x1a: case 0x1a:
return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output, fd); return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output, fd);
case 0x1b: case 0x1b:
return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, fd, true); return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true);
case 0x1d: case 0x1d:
return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output); return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output);
default: default:
@@ -387,19 +387,8 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandL
return NvResult::Success; return NvResult::Success;
} }
Core::Memory::Memory& nvhost_gpu::GetSessionMemory(DeviceFD fd) {
if (const auto it = sessions.find(fd); it != sessions.end())
if (auto* const session = core.GetSession(it->second);
session != nullptr && session->process != nullptr)
return session->process->GetMemory();
LOG_ERROR(Service_NVDRV, "No session for fd={}, falling back to application memory", fd);
return system.ApplicationMemory();
}
NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
std::span<Tegra::CommandListHeader> commands, DeviceFD fd, std::span<Tegra::CommandListHeader> commands, bool kickoff) {
bool kickoff) {
if (params.num_entries > commands.size()) { if (params.num_entries > commands.size()) {
UNIMPLEMENTED(); UNIMPLEMENTED();
return NvResult::InvalidSize; return NvResult::InvalidSize;
@@ -407,7 +396,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
Tegra::CommandList entries(params.num_entries); Tegra::CommandList entries(params.num_entries);
if (kickoff) { if (kickoff) {
this->GetSessionMemory(fd).ReadBlock(params.address, entries.command_lists.data(), system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(),
params.num_entries * sizeof(Tegra::CommandListHeader)); params.num_entries * sizeof(Tegra::CommandListHeader));
} else { } else {
std::memcpy(entries.command_lists.data(), commands.data(), std::memcpy(entries.command_lists.data(), commands.data(),
@@ -16,10 +16,6 @@
#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvdrv/nvdata.h"
#include "video_core/dma_pusher.h" #include "video_core/dma_pusher.h"
namespace Core::Memory {
class Memory;
}
namespace Tegra { namespace Tegra {
namespace Control { namespace Control {
struct ChannelState; struct ChannelState;
@@ -200,11 +196,8 @@ private:
NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries);
Core::Memory::Memory& GetSessionMemory(DeviceFD fd);
NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
std::span<Tegra::CommandListHeader> commands, DeviceFD fd, std::span<Tegra::CommandListHeader> commands, bool kickoff = false);
bool kickoff = false);
NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
std::span<const Tegra::CommandListHeader> commands); std::span<const Tegra::CommandListHeader> commands);
+2 -4
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -15,8 +15,7 @@ struct Layer {
explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_, explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_,
s32 consumer_id_) s32 consumer_id_)
: buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_), : buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_),
blending(LayerBlending::None), visible(true), z_index(0), is_overlay(false), blending(LayerBlending::None), visible(true), z_index(0), is_overlay(false) {}
layer_stack_mask(DefaultLayerStackMask) {}
~Layer() { ~Layer() {
buffer_item_consumer->Abandon(); buffer_item_consumer->Abandon();
} }
@@ -27,7 +26,6 @@ struct Layer {
bool visible; bool visible;
s32 z_index; s32 z_index;
bool is_overlay; bool is_overlay;
u32 layer_stack_mask;
}; };
struct LayerStack { struct LayerStack {
@@ -115,7 +115,6 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
.transform = static_cast<android::BufferTransformFlags>(item.transform), .transform = static_cast<android::BufferTransformFlags>(item.transform),
.crop_rect = item.crop, .crop_rect = item.crop,
.acquire_fence = item.fence, .acquire_fence = item.fence,
.layer_stack_mask = layer->layer_stack_mask,
}); });
} }
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
@@ -26,25 +23,6 @@ enum class LayerBlending : u32 {
Coverage = 0x405, Coverage = 0x405,
}; };
enum class LayerStackId : u32 {
Default = 0,
Lcd = 1,
Screenshot = 2,
Recording = 3,
LastFrame = 4,
Arbitrary = 5,
ApplicationForDebug = 6,
Null = 10,
};
constexpr u32 LayerStackBit(LayerStackId id) {
return 1U << static_cast<u32>(id);
}
constexpr u32 DefaultLayerStackMask =
LayerStackBit(LayerStackId::Default) | LayerStackBit(LayerStackId::Screenshot) |
LayerStackBit(LayerStackId::Recording) | LayerStackBit(LayerStackId::LastFrame);
struct HwcLayer { struct HwcLayer {
u32 buffer_handle; u32 buffer_handle;
u32 offset; u32 offset;
@@ -57,7 +35,6 @@ struct HwcLayer {
android::BufferTransformFlags transform; android::BufferTransformFlags transform;
Common::Rectangle<int> crop_rect; Common::Rectangle<int> crop_rect;
android::Fence acquire_fence; android::Fence acquire_fence;
u32 layer_stack_mask;
}; };
} // namespace Service::Nvnflinger } // namespace Service::Nvnflinger
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -104,14 +104,6 @@ void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blen
} }
} }
void SurfaceFlinger::SetLayerStackMask(s32 consumer_binder_id, u32 layer_stack_mask) {
if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
layer->layer_stack_mask = layer_stack_mask;
LOG_DEBUG(Service_VI, "Layer {} stack mask set to {:#x}", consumer_binder_id,
layer_stack_mask);
}
}
void SurfaceFlinger::SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay) { void SurfaceFlinger::SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay) {
if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) { if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
layer->is_overlay = is_overlay; layer->is_overlay = is_overlay;
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -48,7 +48,6 @@ public:
void SetLayerVisibility(s32 consumer_binder_id, bool visible); void SetLayerVisibility(s32 consumer_binder_id, bool visible);
void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending); void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending);
void SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay); void SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay);
void SetLayerStackMask(s32 consumer_binder_id, u32 layer_stack_mask);
std::shared_ptr<Layer> FindLayer(s32 consumer_binder_id); std::shared_ptr<Layer> FindLayer(s32 consumer_binder_id);
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -13,10 +13,8 @@
namespace Service::PCTL { namespace Service::PCTL {
IParentalControlService::IParentalControlService(Core::System& system_, Capability capability_, IParentalControlService::IParentalControlService(Core::System& system_, Capability capability_)
u64 program_id_)
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_}, : ServiceFramework{system_, "IParentalControlService"}, capability{capability_},
program_id{program_id_},
service_context{system_, "IParentalControlService"}, synchronization_event{service_context}, service_context{system_, "IParentalControlService"}, synchronization_event{service_context},
unlinked_event{service_context}, request_suspension_event{service_context} { unlinked_event{service_context}, request_suspension_event{service_context} {
// clang-format off // clang-format off
@@ -204,6 +202,7 @@ Result IParentalControlService::Initialize() {
// TODO(ogniK): Recovery flag initialization for pctl:r // TODO(ogniK): Recovery flag initialization for pctl:r
const auto program_id = system.GetApplicationProcessProgramID();
if (program_id != 0) { if (program_id != 0) {
const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), const FileSys::PatchManager pm{program_id, system.GetFileSystemController(),
system.GetContentProvider()}; system.GetContentProvider()};
@@ -16,8 +16,7 @@ namespace Service::PCTL {
class IParentalControlService final : public ServiceFramework<IParentalControlService> { class IParentalControlService final : public ServiceFramework<IParentalControlService> {
public: public:
explicit IParentalControlService(Core::System& system_, Capability capability_, explicit IParentalControlService(Core::System& system_, Capability capability_);
u64 program_id_);
~IParentalControlService() override; ~IParentalControlService() override;
private: private:
@@ -85,7 +84,6 @@ private:
RestrictionSettings restriction_settings{}; RestrictionSettings restriction_settings{};
std::array<char, 8> pin_code{}; std::array<char, 8> pin_code{};
Capability capability{}; Capability capability{};
u64 program_id{};
// TODO: this is raw // TODO: this is raw
PlayTimerSettings raw_play_timer_settings{}; PlayTimerSettings raw_play_timer_settings{};
@@ -1,10 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// 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/core.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/pctl/parental_control_service.h" #include "core/hle/service/pctl/parental_control_service.h"
#include "core/hle/service/pctl/parental_control_service_factory.h" #include "core/hle/service/pctl/parental_control_service_factory.h"
@@ -27,17 +23,17 @@ IParentalControlServiceFactory::~IParentalControlServiceFactory() = default;
Result IParentalControlServiceFactory::CreateService( Result IParentalControlServiceFactory::CreateService(
Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) { Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) {
LOG_DEBUG(Service_PCTL, "called, process_id={}", process_id.pid); LOG_DEBUG(Service_PCTL, "called");
*out_service = std::make_shared<IParentalControlService>( // TODO(ogniK): Get application id from process
system, capability, system.ResolveCallerProgramId(*process_id)); *out_service = std::make_shared<IParentalControlService>(system, capability);
R_SUCCEED(); R_SUCCEED();
} }
Result IParentalControlServiceFactory::CreateServiceWithoutInitialize( Result IParentalControlServiceFactory::CreateServiceWithoutInitialize(
Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) { Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) {
LOG_DEBUG(Service_PCTL, "called, process_id={}", process_id.pid); LOG_DEBUG(Service_PCTL, "called");
*out_service = std::make_shared<IParentalControlService>( // TODO(ogniK): Get application id from process
system, capability, system.ResolveCallerProgramId(*process_id)); *out_service = std::make_shared<IParentalControlService>(system, capability);
R_SUCCEED(); R_SUCCEED();
} }
+5 -2
View File
@@ -132,7 +132,8 @@ private:
LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
auto process = kernel.GetProcessByProcessId(pid); auto list = kernel.GetProcessList();
auto process = SearchProcessList(system.Kernel(), list, [pid](auto& p) { return p->GetProcessId() == pid; });
if (process.IsNull()) { if (process.IsNull()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@@ -185,7 +186,9 @@ private:
LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id);
auto process = kernel.GetProcessByProcessId(process_id); auto list = kernel.GetProcessList();
auto process = SearchProcessList(system.Kernel(),
list, [process_id](auto& p) { return p->GetProcessId() == process_id; });
if (process.IsNull()) { if (process.IsNull()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};

Some files were not shown because too many files have changed in this diff Show More