Compare commits
40 Commits
android-21
...
android-22
Author | SHA1 | Date | |
---|---|---|---|
bfe34d6ee8 | |||
3d21af61db | |||
74f5e1dcf5 | |||
f75119322d | |||
a8956d3ff0 | |||
2f5941e899 | |||
a4b147f525 | |||
4240f2d56b | |||
ffe3984353 | |||
ec734cb06c | |||
8292ba7ad6 | |||
2e65616761 | |||
07aa1a99fa | |||
6524f20de4 | |||
a0f7f2b309 | |||
ecea5ef757 | |||
a1ce45b0b1 | |||
9ba9780a96 | |||
73e7a259fd | |||
2cc5c517cf | |||
c0775e74ec | |||
3acf35bb98 | |||
8ddfecfbae | |||
51f5a6f1f8 | |||
64fca24b32 | |||
ba4cee1812 | |||
06abf3205a | |||
adfdc9520a | |||
90cb852908 | |||
278dd589ec | |||
15e8791f9d | |||
498c9bd96a | |||
6c8df6af44 | |||
8e93537266 | |||
b8f16f3538 | |||
6cc82fd430 | |||
2bc0132d0c | |||
da410506a4 | |||
23e074ff14 | |||
f854ffd015 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -64,3 +64,6 @@
|
|||||||
[submodule "oaknut"]
|
[submodule "oaknut"]
|
||||||
path = externals/oaknut
|
path = externals/oaknut
|
||||||
url = https://github.com/merryhime/oaknut
|
url = https://github.com/merryhime/oaknut
|
||||||
|
[submodule "Vulkan-Utility-Libraries"]
|
||||||
|
path = externals/Vulkan-Utility-Libraries
|
||||||
|
url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
|
||||||
|
@ -36,6 +36,8 @@ option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
|
|||||||
|
|
||||||
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
||||||
|
|
||||||
|
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
|
||||||
|
|
||||||
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
|
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
|
||||||
|
|
||||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||||
@ -308,6 +310,10 @@ if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
|||||||
find_package(Vulkan 1.3.274 REQUIRED)
|
find_package(Vulkan 1.3.274 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||||
|
find_package(VulkanUtilityLibraries REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (ENABLE_LIBUSB)
|
if (ENABLE_LIBUSB)
|
||||||
find_package(libusb 1.0.24 MODULE)
|
find_package(libusb 1.0.24 MODULE)
|
||||||
endif()
|
endif()
|
||||||
@ -316,6 +322,10 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
|||||||
find_package(xbyak 6 CONFIG)
|
find_package(xbyak 6 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ARCHITECTURE_arm64)
|
||||||
|
find_package(oaknut 2.0.1 CONFIG)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||||
find_package(dynarmic 6.4.0 CONFIG)
|
find_package(dynarmic 6.4.0 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
11
README.md
11
README.md
@ -1,9 +1,12 @@
|
|||||||
| Pull Request | Commit | Title | Author | Merged? |
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|----|----|----|----|----|
|
|----|----|----|----|----|
|
||||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`c6b88b62d`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`817d91623`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [12814](https://github.com/yuzu-emu/yuzu-android//pull/12814) | [`da410506a`](https://github.com/yuzu-emu/yuzu-android//pull/12814/files) | Move time services to new IPC and add debug printing | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
| [12858](https://github.com/yuzu-emu/yuzu-android//pull/12858) | [`5510b3197`](https://github.com/yuzu-emu/yuzu-android//pull/12858/files) | internal_network: only poll for accept on blocking sockets | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [12830](https://github.com/yuzu-emu/yuzu-android//pull/12830) | [`6cc82fd43`](https://github.com/yuzu-emu/yuzu-android//pull/12830/files) | externals/dynarmic: Update to 6.6.1 | [merryhime](https://github.com/merryhime/) | Yes |
|
| [12864](https://github.com/yuzu-emu/yuzu-android//pull/12864) | [`9ed82a280`](https://github.com/yuzu-emu/yuzu-android//pull/12864/files) | Small time fixes | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||||
|
| [12867](https://github.com/yuzu-emu/yuzu-android//pull/12867) | [`a97ecc237`](https://github.com/yuzu-emu/yuzu-android//pull/12867/files) | aoc: fix DLC listing | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
| [12868](https://github.com/yuzu-emu/yuzu-android//pull/12868) | [`e8be665f1`](https://github.com/yuzu-emu/yuzu-android//pull/12868/files) | settings: Allow audio sink, input, and output to be set per game | [t895](https://github.com/t895/) | Yes |
|
||||||
|
| [12869](https://github.com/yuzu-emu/yuzu-android//pull/12869) | [`acd46c9bd`](https://github.com/yuzu-emu/yuzu-android//pull/12869/files) | SMMU: A set of different fixes. | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||||
|
|
||||||
|
|
||||||
End of merge log. You can find the original README.md below the break.
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
10
externals/CMakeLists.txt
vendored
10
externals/CMakeLists.txt
vendored
@ -14,16 +14,17 @@ set(BUILD_SHARED_LIBS OFF)
|
|||||||
# Skip install rules for all externals
|
# Skip install rules for all externals
|
||||||
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||||
|
|
||||||
# xbyak
|
# Xbyak (also used by Dynarmic, so needs to be added first)
|
||||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||||
add_subdirectory(xbyak)
|
add_subdirectory(xbyak)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Dynarmic
|
# Oaknut (also used by Dynarmic, so needs to be added first)
|
||||||
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
||||||
add_subdirectory(oaknut)
|
add_subdirectory(oaknut)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Dynarmic
|
||||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||||
set(DYNARMIC_IGNORE_ASSERTS ON)
|
set(DYNARMIC_IGNORE_ASSERTS ON)
|
||||||
add_subdirectory(dynarmic)
|
add_subdirectory(dynarmic)
|
||||||
@ -154,6 +155,11 @@ if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
|||||||
add_subdirectory(Vulkan-Headers)
|
add_subdirectory(Vulkan-Headers)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Vulkan-Utility-Libraries
|
||||||
|
if (YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
|
||||||
|
add_subdirectory(Vulkan-Utility-Libraries)
|
||||||
|
endif()
|
||||||
|
|
||||||
# TZDB (Time Zone Database)
|
# TZDB (Time Zone Database)
|
||||||
add_subdirectory(nx_tzdb)
|
add_subdirectory(nx_tzdb)
|
||||||
|
|
||||||
|
1
externals/Vulkan-Utility-Libraries
vendored
Submodule
1
externals/Vulkan-Utility-Libraries
vendored
Submodule
Submodule externals/Vulkan-Utility-Libraries added at 524f8910d0
@ -261,7 +261,7 @@ object NativeLibrary {
|
|||||||
/**
|
/**
|
||||||
* Begins emulation.
|
* Begins emulation.
|
||||||
*/
|
*/
|
||||||
external fun run(path: String?, programIndex: Int = 0)
|
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
|
||||||
|
|
||||||
// Surface Handling
|
// Surface Handling
|
||||||
external fun surfaceChanged(surf: Surface?)
|
external fun surfaceChanged(surf: Surface?)
|
||||||
|
@ -7,6 +7,7 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding
|
import org.yuzu.yuzu_emu.databinding.CardDriverOptionBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.model.Driver
|
import org.yuzu.yuzu_emu.model.Driver
|
||||||
@ -57,13 +58,9 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) :
|
|||||||
title.text = model.title
|
title.text = model.title
|
||||||
version.text = model.version
|
version.text = model.version
|
||||||
description.text = model.description
|
description.text = model.description
|
||||||
if (model.description.isNotEmpty()) {
|
if (model.title != binding.root.context.getString(R.string.system_gpu_driver)) {
|
||||||
version.visibility = View.VISIBLE
|
|
||||||
description.visibility = View.VISIBLE
|
|
||||||
buttonDelete.visibility = View.VISIBLE
|
buttonDelete.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
version.visibility = View.GONE
|
|
||||||
description.visibility = View.GONE
|
|
||||||
buttonDelete.visibility = View.GONE
|
buttonDelete.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
emulationThread.join()
|
emulationThread.join()
|
||||||
emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath, programIndex)
|
NativeLibrary.run(gamePath, programIndex, false)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
State.STOPPED -> {
|
State.STOPPED -> {
|
||||||
emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath, programIndex)
|
NativeLibrary.run(gamePath, programIndex, true)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,8 @@ void EmulationSession::SetAppletId(int applet_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
||||||
const std::size_t program_index) {
|
const std::size_t program_index,
|
||||||
|
const bool frontend_initiated) {
|
||||||
std::scoped_lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
// Create the render window.
|
// Create the render window.
|
||||||
@ -251,6 +252,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
// Load the ROM.
|
// Load the ROM.
|
||||||
Service::AM::FrontendAppletParameters params{
|
Service::AM::FrontendAppletParameters params{
|
||||||
.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
|
||||||
|
: Service::AM::LaunchType::ApplicationInitiated,
|
||||||
.program_index = static_cast<s32>(program_index),
|
.program_index = static_cast<s32>(program_index),
|
||||||
};
|
};
|
||||||
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||||
@ -447,7 +450,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||||
const size_t program_index = 0) {
|
const size_t program_index,
|
||||||
|
const bool frontend_initiated) {
|
||||||
MicroProfileOnThreadCreate("EmuThread");
|
MicroProfileOnThreadCreate("EmuThread");
|
||||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||||
|
|
||||||
@ -460,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
|||||||
|
|
||||||
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
||||||
|
|
||||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
|
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
|
||||||
|
frontend_initiated);
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -757,10 +762,12 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||||
jint j_program_index) {
|
jint j_program_index,
|
||||||
|
jboolean j_frontend_initiated) {
|
||||||
const std::string path = GetJString(env, j_path);
|
const std::string path = GetJString(env, j_path);
|
||||||
|
|
||||||
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
|
const Core::SystemResultStatus result{
|
||||||
|
RunEmulation(path, j_program_index, j_frontend_initiated)};
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||||
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||||
|
@ -47,7 +47,8 @@ public:
|
|||||||
void InitializeSystem(bool reload);
|
void InitializeSystem(bool reload);
|
||||||
void SetAppletId(int applet_id);
|
void SetAppletId(int applet_id);
|
||||||
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
||||||
const std::size_t program_index = 0);
|
const std::size_t program_index,
|
||||||
|
const bool frontend_initiated);
|
||||||
|
|
||||||
bool IsHandheldOnly();
|
bool IsHandheldOnly();
|
||||||
void SetDeviceType([[maybe_unused]] int index, int type);
|
void SetDeviceType([[maybe_unused]] int index, int type);
|
||||||
|
@ -134,12 +134,12 @@ struct Values {
|
|||||||
Linkage linkage{};
|
Linkage linkage{};
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
|
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
|
||||||
Specialization::RuntimeList};
|
Category::Audio, Specialization::RuntimeList};
|
||||||
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
|
SwitchableSetting<std::string> audio_output_device_id{
|
||||||
Specialization::RuntimeList};
|
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
|
||||||
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
|
SwitchableSetting<std::string> audio_input_device_id{
|
||||||
Specialization::RuntimeList};
|
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
|
||||||
SwitchableSetting<AudioMode, true> sound_index{
|
SwitchableSetting<AudioMode, true> sound_index{
|
||||||
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
||||||
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <bit>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -181,24 +182,28 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||||
static constexpr size_t subentries = 8 / sizeof(u8);
|
using CounterType = u8;
|
||||||
|
using CounterAtomicType = std::atomic_uint8_t;
|
||||||
|
static constexpr size_t subentries = 8 / sizeof(CounterType);
|
||||||
static constexpr size_t subentries_mask = subentries - 1;
|
static constexpr size_t subentries_mask = subentries - 1;
|
||||||
|
static constexpr size_t subentries_shift =
|
||||||
|
std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
|
||||||
class CounterEntry final {
|
class CounterEntry final {
|
||||||
public:
|
public:
|
||||||
CounterEntry() = default;
|
CounterEntry() = default;
|
||||||
|
|
||||||
std::atomic_uint8_t& Count(std::size_t page) {
|
CounterAtomicType& Count(std::size_t page) {
|
||||||
return values[page & subentries_mask];
|
return values[page & subentries_mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::atomic_uint8_t& Count(std::size_t page) const {
|
const CounterAtomicType& Count(std::size_t page) const {
|
||||||
return values[page & subentries_mask];
|
return values[page & subentries_mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<std::atomic_uint8_t, subentries> values{};
|
std::array<CounterAtomicType, subentries> values{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
|
static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType),
|
||||||
"CounterEntry should be 8 bytes!");
|
"CounterEntry should be 8 bytes!");
|
||||||
|
|
||||||
static constexpr size_t num_counter_entries =
|
static constexpr size_t num_counter_entries =
|
||||||
|
@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Traits>
|
template <typename Traits>
|
||||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
|
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid,
|
||||||
Asid asid, bool track) {
|
bool track) {
|
||||||
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||||
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||||
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||||
@ -519,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
|||||||
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
|
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
|
||||||
size_t page = addr >> Memory::YUZU_PAGEBITS;
|
size_t page = addr >> Memory::YUZU_PAGEBITS;
|
||||||
auto [asid, base_vaddress] = ExtractCPUBacking(page);
|
auto [asid, base_vaddress] = ExtractCPUBacking(page);
|
||||||
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
|
||||||
auto* memory_device_inter = registered_processes[asid.id];
|
auto* memory_device_inter = registered_processes[asid.id];
|
||||||
|
const auto release_pending = [&] {
|
||||||
|
if (uncache_bytes > 0) {
|
||||||
|
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
|
||||||
|
uncache_bytes, false);
|
||||||
|
uncache_bytes = 0;
|
||||||
|
}
|
||||||
|
if (cache_bytes > 0) {
|
||||||
|
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||||
|
cache_bytes, true);
|
||||||
|
cache_bytes = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
for (; page != page_end; ++page) {
|
for (; page != page_end; ++page) {
|
||||||
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
|
CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page);
|
||||||
|
auto [asid_2, vpage] = ExtractCPUBacking(page);
|
||||||
|
vpage >>= Memory::YUZU_PAGEBITS;
|
||||||
|
|
||||||
if (delta > 0) {
|
if (vpage == 0) [[unlikely]] {
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
|
release_pending();
|
||||||
"Count may overflow!");
|
continue;
|
||||||
} else if (delta < 0) {
|
}
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
|
||||||
} else {
|
if (asid.id != asid_2.id) [[unlikely]] {
|
||||||
ASSERT_MSG(false, "Delta must be non-zero!");
|
release_pending();
|
||||||
|
memory_device_inter = registered_processes[asid_2.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
||||||
count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
|
count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release);
|
||||||
|
|
||||||
// Assume delta is either -1 or 1
|
// Assume delta is either -1 or 1
|
||||||
if (count.load(std::memory_order::relaxed) == 0) {
|
if (count.load(std::memory_order::relaxed) == 0) {
|
||||||
@ -553,20 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
|||||||
}
|
}
|
||||||
cache_bytes += Memory::YUZU_PAGESIZE;
|
cache_bytes += Memory::YUZU_PAGESIZE;
|
||||||
} else if (cache_bytes > 0) {
|
} else if (cache_bytes > 0) {
|
||||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||||
true);
|
cache_bytes, true);
|
||||||
cache_bytes = 0;
|
cache_bytes = 0;
|
||||||
}
|
}
|
||||||
vpage++;
|
|
||||||
}
|
|
||||||
if (uncache_bytes > 0) {
|
|
||||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
if (cache_bytes > 0) {
|
|
||||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
release_pending();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@ -303,8 +303,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Applet was started by frontend, so it is foreground.
|
// Applet was started by frontend, so it is foreground.
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
applet->focus_state = FocusState::InFocus;
|
applet->focus_state = FocusState::InFocus;
|
||||||
|
|
||||||
this->InsertApplet(std::move(applet));
|
this->InsertApplet(std::move(applet));
|
||||||
|
@ -207,7 +207,7 @@ void Error::Execute() {
|
|||||||
|
|
||||||
void Error::DisplayCompleted() {
|
void Error::DisplayCompleted() {
|
||||||
complete = true;
|
complete = true;
|
||||||
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>()));
|
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||||
Exit();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,24 +85,26 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
|||||||
applet->library_applet_mode = mode;
|
applet->library_applet_mode = mode;
|
||||||
|
|
||||||
// Set focus state
|
// Set focus state
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case LibraryAppletMode::AllForeground:
|
case LibraryAppletMode::AllForeground:
|
||||||
case LibraryAppletMode::NoUI:
|
case LibraryAppletMode::NoUI:
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
|
||||||
applet->focus_state = FocusState::InFocus;
|
applet->focus_state = FocusState::InFocus;
|
||||||
applet->hid_registration.EnableAppletToGetInput(true);
|
applet->hid_registration.EnableAppletToGetInput(true);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
break;
|
break;
|
||||||
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
||||||
applet->system_buffer_manager.SetWindowVisibility(false);
|
applet->system_buffer_manager.SetWindowVisibility(false);
|
||||||
applet->focus_state = FocusState::NotInFocus;
|
applet->focus_state = FocusState::NotInFocus;
|
||||||
applet->hid_registration.EnableAppletToGetInput(false);
|
applet->hid_registration.EnableAppletToGetInput(false);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
break;
|
break;
|
||||||
case LibraryAppletMode::Background:
|
case LibraryAppletMode::Background:
|
||||||
case LibraryAppletMode::BackgroundIndirectDisplay:
|
case LibraryAppletMode::BackgroundIndirectDisplay:
|
||||||
default:
|
default:
|
||||||
applet->focus_state = FocusState::Background;
|
applet->focus_state = FocusState::Background;
|
||||||
applet->hid_registration.EnableAppletToGetInput(true);
|
applet->hid_registration.EnableAppletToGetInput(true);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ void AOC_U::ListAddOnContent(HLERequestContext& ctx) {
|
|||||||
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);
|
process_id);
|
||||||
|
|
||||||
const auto current = system.GetApplicationProcessProgramID();
|
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];
|
||||||
|
@ -122,14 +122,14 @@ struct RequestLayout {
|
|||||||
u32 domain_interface_count;
|
u32 domain_interface_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||||
constexpr u32 GetArgumentRawDataSize() {
|
constexpr u32 GetInRawDataSize() {
|
||||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||||
return static_cast<u32>(DataOffset);
|
return static_cast<u32>(DataOffset);
|
||||||
} else {
|
} else {
|
||||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||||
|
|
||||||
if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) {
|
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) {
|
||||||
constexpr size_t ArgAlign = alignof(ArgType);
|
constexpr size_t ArgAlign = alignof(ArgType);
|
||||||
constexpr size_t ArgSize = sizeof(ArgType);
|
constexpr size_t ArgSize = sizeof(ArgType);
|
||||||
|
|
||||||
@ -138,9 +138,33 @@ constexpr u32 GetArgumentRawDataSize() {
|
|||||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||||
|
|
||||||
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||||
} else {
|
} else {
|
||||||
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||||
|
constexpr u32 GetOutRawDataSize() {
|
||||||
|
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||||
|
return static_cast<u32>(DataOffset);
|
||||||
|
} else {
|
||||||
|
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||||
|
|
||||||
|
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||||
|
using RawArgType = typename ArgType::Type;
|
||||||
|
constexpr size_t ArgAlign = alignof(RawArgType);
|
||||||
|
constexpr size_t ArgSize = sizeof(RawArgType);
|
||||||
|
|
||||||
|
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||||
|
|
||||||
|
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||||
|
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||||
|
|
||||||
|
return GetOutRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||||
|
} else {
|
||||||
|
return GetOutRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,7 +189,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = 0,
|
.move_handle_count = 0,
|
||||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
||||||
.domain_interface_count = 0,
|
.domain_interface_count = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -175,7 +199,7 @@ constexpr RequestLayout GetDomainReplyInLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = 0,
|
.move_handle_count = 0,
|
||||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
||||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
|
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -185,7 +209,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
||||||
.domain_interface_count = 0,
|
.domain_interface_count = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -195,7 +219,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
|
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
|
||||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
||||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -259,7 +283,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
|||||||
|
|
||||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(ArgType);
|
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||||
|
|
||||||
// Clear the existing data.
|
// Clear the existing data.
|
||||||
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
||||||
@ -300,7 +324,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
|||||||
|
|
||||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(ArgType);
|
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||||
|
|
||||||
// Clear the existing data.
|
// Clear the existing data.
|
||||||
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
|
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
|
||||||
@ -337,13 +361,15 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
|||||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||||
|
|
||||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||||
constexpr size_t ArgAlign = alignof(ArgType);
|
using RawArgType = decltype(std::get<ArgIndex>(args).raw);
|
||||||
constexpr size_t ArgSize = sizeof(ArgType);
|
constexpr size_t ArgAlign = alignof(RawArgType);
|
||||||
|
constexpr size_t ArgSize = sizeof(RawArgType);
|
||||||
|
|
||||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||||
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
|
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
|
||||||
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
|
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
|
||||||
static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable");
|
static_assert(!std::is_pointer_v<RawArgType>, "Output raw data must not be a pointer");
|
||||||
|
static_assert(std::is_trivially_copyable_v<RawArgType>, "Output raw data must be trivially copyable");
|
||||||
|
|
||||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||||
@ -368,7 +394,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
|||||||
|
|
||||||
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(ArgType);
|
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||||
|
|
||||||
ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
|
ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
|
||||||
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
|
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
|
||||||
|
@ -197,32 +197,27 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(
|
|||||||
|
|
||||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count,
|
const Service::PSC::Time::CalendarTime& calendar_time,
|
||||||
Service::PSC::Time::CalendarTime& calendar_time, InRule rule) {
|
InRule rule) {
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
LOG_DEBUG(Service_Time,
|
LOG_DEBUG(Service_Time,
|
||||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||||
"out_times_count={}",
|
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
R_RETURN(
|
R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));
|
||||||
m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
Result TimeZoneService::ToPosixTimeWithMyRule(
|
||||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count,
|
const Service::PSC::Time::CalendarTime& calendar_time) {
|
||||||
Service::PSC::Time::CalendarTime& calendar_time) {
|
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
LOG_DEBUG(Service_Time,
|
LOG_DEBUG(Service_Time,
|
||||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||||
"out_times_count={}",
|
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count,
|
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));
|
||||||
calendar_time));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::Glue::Time
|
} // namespace Service::Glue::Time
|
||||||
|
@ -68,12 +68,10 @@ public:
|
|||||||
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
||||||
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time);
|
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time,
|
const Service::PSC::Time::CalendarTime& calendar_time, InRule rule);
|
||||||
InRule rule);
|
|
||||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count,
|
const Service::PSC::Time::CalendarTime& calendar_time);
|
||||||
Service::PSC::Time::CalendarTime& calendar_time);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "core/hle/kernel/k_shared_memory.h"
|
#include "core/hle/kernel/k_shared_memory.h"
|
||||||
#include "core/hle/kernel/k_transfer_memory.h"
|
#include "core/hle/kernel/k_transfer_memory.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
#include "core/hle/service/hid/hid_server.h"
|
#include "core/hle/service/hid/hid_server.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
@ -153,7 +154,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
|
|||||||
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
|
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
|
||||||
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
|
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
|
||||||
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
|
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
|
||||||
{108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
|
{108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"},
|
||||||
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
|
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
|
||||||
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
|
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
|
||||||
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
|
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
|
||||||
@ -1136,19 +1137,39 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
|
|||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
|
Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
||||||
IPC::RequestParser rp{ctx};
|
Core::HID::NpadIdType npad_id) {
|
||||||
const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
|
|
||||||
|
|
||||||
Core::HID::LedPattern pattern{0, 0, 0, 0};
|
|
||||||
auto controller = GetResourceManager()->GetNpad();
|
|
||||||
const auto result = controller->GetLedPattern(npad_id, pattern);
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
|
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
switch (npad_id) {
|
||||||
rb.Push(result);
|
case Core::HID::NpadIdType::Player1:
|
||||||
rb.Push(pattern.raw);
|
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player2:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{1, 1, 0, 0};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player3:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 0};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player4:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 1};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player5:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 1};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player6:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 0};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player7:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 1};
|
||||||
|
R_SUCCEED();
|
||||||
|
case Core::HID::NpadIdType::Player8:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{0, 1, 1, 0};
|
||||||
|
R_SUCCEED();
|
||||||
|
default:
|
||||||
|
*out_led_pattern = Core::HID::LedPattern{0, 0, 0, 0};
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
@ -66,7 +68,8 @@ private:
|
|||||||
void DeactivateNpad(HLERequestContext& ctx);
|
void DeactivateNpad(HLERequestContext& ctx);
|
||||||
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
||||||
void DisconnectNpad(HLERequestContext& ctx);
|
void DisconnectNpad(HLERequestContext& ctx);
|
||||||
void GetPlayerLedPattern(HLERequestContext& ctx);
|
Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
||||||
|
Core::HID::NpadIdType npad_id);
|
||||||
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
||||||
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
||||||
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
||||||
|
@ -111,7 +111,8 @@ private:
|
|||||||
R_RETURN(result);
|
R_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) {
|
Result UpdateLatest(Out<CharInfo> out_char_info, const CharInfo& char_info,
|
||||||
|
SourceFlag source_flag) {
|
||||||
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
|
|
||||||
R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
|
R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
|
||||||
@ -159,7 +160,7 @@ private:
|
|||||||
R_RETURN(result);
|
R_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data,
|
Result UpdateLatest1(Out<StoreData> out_store_data, const StoreData& store_data,
|
||||||
SourceFlag source_flag) {
|
SourceFlag source_flag) {
|
||||||
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
||||||
R_UNLESS(is_system, ResultPermissionDenied);
|
R_UNLESS(is_system, ResultPermissionDenied);
|
||||||
@ -243,7 +244,7 @@ private:
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
|
Result GetIndex(Out<s32> out_index, const CharInfo& char_info) {
|
||||||
LOG_DEBUG(Service_Mii, "called");
|
LOG_DEBUG(Service_Mii, "called");
|
||||||
|
|
||||||
R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
|
R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
|
||||||
@ -257,25 +258,25 @@ private:
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) {
|
Result Convert(Out<CharInfo> out_char_info, const Ver3StoreData& mii_v3) {
|
||||||
LOG_INFO(Service_Mii, "called");
|
LOG_INFO(Service_Mii, "called");
|
||||||
|
|
||||||
R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
|
R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) {
|
Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, const CoreData& core_data) {
|
||||||
LOG_INFO(Service_Mii, "called");
|
LOG_INFO(Service_Mii, "called");
|
||||||
|
|
||||||
R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
|
R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) {
|
Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, const CharInfo& char_info) {
|
||||||
LOG_INFO(Service_Mii, "called");
|
LOG_INFO(Service_Mii, "called");
|
||||||
|
|
||||||
R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
|
R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Append(CharInfo& char_info) {
|
Result Append(const CharInfo& char_info) {
|
||||||
LOG_INFO(Service_Mii, "called");
|
LOG_INFO(Service_Mii, "called");
|
||||||
|
|
||||||
R_RETURN(manager->Append(metadata, char_info));
|
R_RETURN(manager->Append(metadata, char_info));
|
||||||
|
@ -83,7 +83,9 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
|
|||||||
|
|
||||||
// Check if this memory block is heap.
|
// Check if this memory block is heap.
|
||||||
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
||||||
if (svc_mem_info.size > region_size) {
|
if (region_start + region_size == svc_mem_info.base_address) {
|
||||||
|
region_size += svc_mem_info.size;
|
||||||
|
} else if (svc_mem_info.size > region_size) {
|
||||||
region_size = svc_mem_info.size;
|
region_size = svc_mem_info.size;
|
||||||
region_start = svc_mem_info.base_address;
|
region_start = svc_mem_info.base_address;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
|
auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
|
||||||
FormatContext& ctx) const {
|
FormatContext& ctx) const {
|
||||||
return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point);
|
return fmt::format_to(ctx.out(), "[time_point={}]", time_point.time_point);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ template <>
|
|||||||
struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
|
struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
|
auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
|
||||||
return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset,
|
return fmt::format_to(ctx.out(), "[offset={} steady_time_point={}]", context.offset,
|
||||||
context.steady_time_point.time_point);
|
context.steady_time_point.time_point);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -206,8 +206,9 @@ template <>
|
|||||||
struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
|
struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
|
auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
|
||||||
return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month,
|
return fmt::format_to(ctx.out(), "[{:02}/{:02}/{:04} {:02}:{:02}:{:02}]", calendar.day,
|
||||||
calendar.year, calendar.hour, calendar.minute, calendar.second);
|
calendar.month, calendar.year, calendar.hour, calendar.minute,
|
||||||
|
calendar.second);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo>
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
|
auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
|
||||||
FormatContext& ctx) const {
|
FormatContext& ctx) const {
|
||||||
return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}",
|
return fmt::format_to(ctx.out(), "[weekday={} yearday={} name={} is_dst={} ut_offset={}]",
|
||||||
additional.day_of_week, additional.day_of_year,
|
additional.day_of_week, additional.day_of_year,
|
||||||
additional.name.data(), additional.is_dst, additional.ut_offset);
|
additional.name.data(), additional.is_dst, additional.ut_offset);
|
||||||
}
|
}
|
||||||
@ -227,8 +228,7 @@ template <>
|
|||||||
struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
|
struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
|
auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
|
||||||
std::string_view n{name.data(), name.size()};
|
return formatter<string_view>::format(name.data(), ctx);
|
||||||
return formatter<string_view>::format(n, ctx);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -236,8 +236,7 @@ template <>
|
|||||||
struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
|
struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
|
auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
|
||||||
std::string_view v{version.data(), version.size()};
|
return formatter<string_view>::format(version.data(), ctx);
|
||||||
return formatter<string_view>::format(v, ctx);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -247,10 +246,11 @@ struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::s
|
|||||||
auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
|
auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
|
||||||
return fmt::format_to(
|
return fmt::format_to(
|
||||||
ctx.out(),
|
ctx.out(),
|
||||||
"user_context={} network_context={} user_time={} network_time={} user_calendar_time={} "
|
"[user_context={} network_context={} user_time={} network_time={} "
|
||||||
|
"user_calendar_time={} "
|
||||||
"network_calendar_time={} user_calendar_additional_time={} "
|
"network_calendar_time={} user_calendar_additional_time={} "
|
||||||
"network_calendar_additional_time={} steady_clock_time_point={} location={} "
|
"network_calendar_additional_time={} steady_clock_time_point={} location={} "
|
||||||
"is_automatic_correction_enabled={} type={}",
|
"is_automatic_correction_enabled={} type={}]",
|
||||||
snapshot.user_context, snapshot.network_context, snapshot.user_time,
|
snapshot.user_context, snapshot.network_context, snapshot.user_time,
|
||||||
snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
|
snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
|
||||||
snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
|
snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
|
||||||
@ -266,7 +266,7 @@ struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint>
|
|||||||
auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
|
auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
|
||||||
FormatContext& ctx) const {
|
FormatContext& ctx) const {
|
||||||
return fmt::format_to(ctx.out(),
|
return fmt::format_to(ctx.out(),
|
||||||
"rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}",
|
"[rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}]",
|
||||||
time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
|
time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
|
||||||
time_point.lower, time_point.upper);
|
time_point.lower, time_point.upper);
|
||||||
}
|
}
|
||||||
|
@ -120,11 +120,8 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
|
|||||||
context, context.steady_time_point.clock_source_id.RawString(), accuracy);
|
context, context.steady_time_point.clock_source_id.RawString(), accuracy);
|
||||||
|
|
||||||
// TODO this is a hack! The network clock should be updated independently, from the ntc service
|
// TODO this is a hack! The network clock should be updated independently, from the ntc service
|
||||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
// and maybe elsewhere. We do not do that, so fix the clock to the local clock.
|
||||||
// to avoid it being stuck at 0.
|
m_local_system_clock.GetContext(context);
|
||||||
if (context == Service::PSC::Time::SystemClockContext{}) {
|
|
||||||
m_local_system_clock.GetContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_network_system_clock.SetContextWriter(m_network_system_context_writer);
|
m_network_system_clock.SetContextWriter(m_network_system_context_writer);
|
||||||
m_network_system_clock.Initialize(context, accuracy);
|
m_network_system_clock.Initialize(context, accuracy);
|
||||||
@ -138,13 +135,6 @@ Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correctio
|
|||||||
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
|
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
|
||||||
automatic_correction, time_point, time_point.clock_source_id.RawString());
|
automatic_correction, time_point, time_point.clock_source_id.RawString());
|
||||||
|
|
||||||
// TODO this is a hack! The user clock should be updated independently, from the ntc service
|
|
||||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
|
||||||
// to avoid it being stuck at 0.
|
|
||||||
if (time_point == Service::PSC::Time::SteadyClockTimePoint{}) {
|
|
||||||
m_local_system_clock.GetCurrentTimePoint(time_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_user_system_clock.SetAutomaticCorrection(automatic_correction);
|
m_user_system_clock.SetAutomaticCorrection(automatic_correction);
|
||||||
m_user_system_clock.SetTimePointAndSignal(time_point);
|
m_user_system_clock.SetTimePointAndSignal(time_point);
|
||||||
m_user_system_clock.SetInitialized();
|
m_user_system_clock.SetInitialized();
|
||||||
|
@ -140,11 +140,11 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary)
|
|||||||
R_RETURN(ParseBinaryImpl(out_rule, binary));
|
R_RETURN(ParseBinaryImpl(out_rule, binary));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||||
CalendarTime& calendar, const Tz::Rule& rule) {
|
const CalendarTime& calendar, const Tz::Rule& rule) {
|
||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
|
|
||||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
|
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, rule, -1);
|
||||||
|
|
||||||
if (res != ResultSuccess) {
|
if (res != ResultSuccess) {
|
||||||
if (res == ResultTimeZoneNotFound) {
|
if (res == ResultTimeZoneNotFound) {
|
||||||
@ -158,10 +158,10 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||||
u32 out_times_count, CalendarTime& calendar) {
|
size_t out_times_max_count, const CalendarTime& calendar) {
|
||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
|
|
||||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, m_my_rule, -1);
|
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, m_my_rule, -1);
|
||||||
|
|
||||||
if (res != ResultSuccess) {
|
if (res != ResultSuccess) {
|
||||||
if (res == ResultTimeZoneNotFound) {
|
if (res == ResultTimeZoneNotFound) {
|
||||||
@ -212,20 +212,23 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times,
|
||||||
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) {
|
size_t out_times_max_count, const CalendarTime& calendar,
|
||||||
|
const Tz::Rule& rule, s32 is_dst) {
|
||||||
R_TRY(ValidateRule(rule));
|
R_TRY(ValidateRule(rule));
|
||||||
|
|
||||||
calendar.month -= 1;
|
CalendarTime local_calendar{calendar};
|
||||||
calendar.year -= 1900;
|
|
||||||
|
local_calendar.month -= 1;
|
||||||
|
local_calendar.year -= 1900;
|
||||||
|
|
||||||
Tz::CalendarTimeInternal internal{
|
Tz::CalendarTimeInternal internal{
|
||||||
.tm_sec = calendar.second,
|
.tm_sec = local_calendar.second,
|
||||||
.tm_min = calendar.minute,
|
.tm_min = local_calendar.minute,
|
||||||
.tm_hour = calendar.hour,
|
.tm_hour = local_calendar.hour,
|
||||||
.tm_mday = calendar.day,
|
.tm_mday = local_calendar.day,
|
||||||
.tm_mon = calendar.month,
|
.tm_mon = local_calendar.month,
|
||||||
.tm_year = calendar.year,
|
.tm_year = local_calendar.year,
|
||||||
.tm_wday = 0,
|
.tm_wday = 0,
|
||||||
.tm_yday = 0,
|
.tm_yday = 0,
|
||||||
.tm_isdst = is_dst,
|
.tm_isdst = is_dst,
|
||||||
@ -243,9 +246,9 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 o
|
|||||||
R_RETURN(ResultTimeZoneNotFound);
|
R_RETURN(ResultTimeZoneNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internal.tm_sec != calendar.second || internal.tm_min != calendar.minute ||
|
if (internal.tm_sec != local_calendar.second || internal.tm_min != local_calendar.minute ||
|
||||||
internal.tm_hour != calendar.hour || internal.tm_mday != calendar.day ||
|
internal.tm_hour != local_calendar.hour || internal.tm_mday != local_calendar.day ||
|
||||||
internal.tm_mon != calendar.month || internal.tm_year != calendar.year) {
|
internal.tm_mon != local_calendar.month || internal.tm_year != local_calendar.year) {
|
||||||
R_RETURN(ResultTimeZoneNotFound);
|
R_RETURN(ResultTimeZoneNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +257,7 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 o
|
|||||||
}
|
}
|
||||||
|
|
||||||
out_times[0] = time;
|
out_times[0] = time;
|
||||||
if (out_times_count < 2) {
|
if (out_times_max_count < 2) {
|
||||||
out_count = 1;
|
out_count = 1;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
@ -38,18 +38,18 @@ public:
|
|||||||
CalendarAdditionalInfo& calendar_additional, s64 time);
|
CalendarAdditionalInfo& calendar_additional, s64 time);
|
||||||
Result ParseBinary(LocationName& name, std::span<const u8> binary);
|
Result ParseBinary(LocationName& name, std::span<const u8> binary);
|
||||||
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
|
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||||
Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||||
CalendarTime& calendar, const Tz::Rule& rule);
|
const CalendarTime& calendar, const Tz::Rule& rule);
|
||||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||||
CalendarTime& calendar);
|
size_t out_times_max_count, const CalendarTime& calendar);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
|
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||||
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||||
const Tz::Rule& rule);
|
const Tz::Rule& rule);
|
||||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||||
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
|
const CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
|
||||||
|
|
||||||
bool m_initialized{};
|
bool m_initialized{};
|
||||||
std::recursive_mutex m_mutex;
|
std::recursive_mutex m_mutex;
|
||||||
|
@ -138,32 +138,28 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_
|
|||||||
|
|
||||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count, CalendarTime& calendar_time,
|
const CalendarTime& calendar_time, InRule rule) {
|
||||||
InRule rule) {
|
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
LOG_DEBUG(Service_Time,
|
LOG_DEBUG(Service_Time,
|
||||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||||
"out_times_count={}",
|
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
R_RETURN(
|
R_RETURN(
|
||||||
m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule));
|
m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count,
|
const CalendarTime& calendar_time) {
|
||||||
CalendarTime& calendar_time) {
|
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
LOG_DEBUG(Service_Time,
|
LOG_DEBUG(Service_Time,
|
||||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||||
"out_times_count={}",
|
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
R_RETURN(
|
R_RETURN(
|
||||||
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time));
|
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::PSC::Time
|
} // namespace Service::PSC::Time
|
||||||
|
@ -50,10 +50,10 @@ public:
|
|||||||
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
||||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time);
|
Out<CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule);
|
const CalendarTime& calendar_time, InRule rule);
|
||||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||||
Out<u32> out_times_count, CalendarTime& calendar_time);
|
const CalendarTime& calendar_time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
|
@ -45,7 +45,7 @@ SystemSettings DefaultSystemSettings() {
|
|||||||
.console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
|
.console_sleep_plan = ConsoleSleepPlan::Sleep1Hour,
|
||||||
};
|
};
|
||||||
|
|
||||||
settings.device_time_zone_location_name = {"UTC"};
|
settings.device_time_zone_location_name = Service::PSC::Time::LocationName{"UTC"};
|
||||||
settings.user_system_clock_automatic_correction_enabled = true;
|
settings.user_system_clock_automatic_correction_enabled = true;
|
||||||
|
|
||||||
settings.primary_album_storage = PrimaryAlbumStorage::SdCard;
|
settings.primary_album_storage = PrimaryAlbumStorage::SdCard;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
namespace Service::Set {
|
namespace Service::Set {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr u32 SETTINGS_VERSION{2u};
|
constexpr u32 SETTINGS_VERSION{3u};
|
||||||
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
|
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
|
||||||
struct SettingsHeader {
|
struct SettingsHeader {
|
||||||
u64 magic;
|
u64 magic;
|
||||||
|
@ -24,6 +24,7 @@ enum class Errno : u32 {
|
|||||||
CONNRESET = 104,
|
CONNRESET = 104,
|
||||||
NOTCONN = 107,
|
NOTCONN = 107,
|
||||||
TIMEDOUT = 110,
|
TIMEDOUT = 110,
|
||||||
|
CONNREFUSED = 111,
|
||||||
INPROGRESS = 115,
|
INPROGRESS = 115,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ Errno Translate(Network::Errno value) {
|
|||||||
return Errno::MFILE;
|
return Errno::MFILE;
|
||||||
case Network::Errno::PIPE:
|
case Network::Errno::PIPE:
|
||||||
return Errno::PIPE;
|
return Errno::PIPE;
|
||||||
|
case Network::Errno::CONNREFUSED:
|
||||||
|
return Errno::CONNREFUSED;
|
||||||
case Network::Errno::NOTCONN:
|
case Network::Errno::NOTCONN:
|
||||||
return Errno::NOTCONN;
|
return Errno::NOTCONN;
|
||||||
case Network::Errno::TIMEDOUT:
|
case Network::Errno::TIMEDOUT:
|
||||||
|
@ -693,20 +693,23 @@ std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
|
|||||||
sockaddr_in addr;
|
sockaddr_in addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
std::vector<WSAPOLLFD> host_pollfds{
|
const bool wait_for_accept = !is_non_blocking;
|
||||||
WSAPOLLFD{fd, POLLIN, 0},
|
if (wait_for_accept) {
|
||||||
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
|
std::vector<WSAPOLLFD> host_pollfds{
|
||||||
};
|
WSAPOLLFD{fd, POLLIN, 0},
|
||||||
|
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
|
||||||
|
};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const int pollres =
|
const int pollres =
|
||||||
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
|
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
|
||||||
if (host_pollfds[1].revents != 0) {
|
if (host_pollfds[1].revents != 0) {
|
||||||
// Interrupt signaled before a client could be accepted, break
|
// Interrupt signaled before a client could be accepted, break
|
||||||
return {AcceptResult{}, Errno::AGAIN};
|
return {AcceptResult{}, Errno::AGAIN};
|
||||||
}
|
}
|
||||||
if (pollres > 0) {
|
if (pollres > 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,6 +916,7 @@ Errno Socket::SetRcvTimeo(u32 value) {
|
|||||||
|
|
||||||
Errno Socket::SetNonBlock(bool enable) {
|
Errno Socket::SetNonBlock(bool enable) {
|
||||||
if (EnableNonBlock(fd, enable)) {
|
if (EnableNonBlock(fd, enable)) {
|
||||||
|
is_non_blocking = enable;
|
||||||
return Errno::SUCCESS;
|
return Errno::SUCCESS;
|
||||||
}
|
}
|
||||||
return GetAndLogLastError();
|
return GetAndLogLastError();
|
||||||
|
@ -166,6 +166,9 @@ public:
|
|||||||
bool IsOpened() const override;
|
bool IsOpened() const override;
|
||||||
|
|
||||||
void HandleProxyPacket(const ProxyPacket& packet) override;
|
void HandleProxyPacket(const ProxyPacket& packet) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_non_blocking = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout);
|
std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout);
|
||||||
|
@ -1091,20 +1091,6 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
|
|||||||
[&] { rasterizer = true; });
|
[&] { rasterizer = true; });
|
||||||
if (rasterizer) {
|
if (rasterizer) {
|
||||||
impl->InvalidateGPUMemory(ptr, size);
|
impl->InvalidateGPUMemory(ptr, size);
|
||||||
|
|
||||||
const auto type = impl->current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type();
|
|
||||||
if (type == Common::PageType::RasterizerCachedMemory) {
|
|
||||||
// Check if device mapped. If not, this bugged and we can unmark.
|
|
||||||
DAddr addr{};
|
|
||||||
Common::ScratchBuffer<u32> buffer;
|
|
||||||
impl->gpu_device_memory->ApplyOpOnPointer(ptr, buffer,
|
|
||||||
[&](DAddr address) { addr = address; });
|
|
||||||
|
|
||||||
if (addr == 0) {
|
|
||||||
LOG_ERROR(HW_Memory, "Fixing unmapped cached region {:#x}", GetInteger(vaddr));
|
|
||||||
impl->RasterizerMarkRegionCached(GetInteger(vaddr), size, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -96,6 +96,7 @@ add_library(hid_core STATIC
|
|||||||
resources/system_buttons/home_button.h
|
resources/system_buttons/home_button.h
|
||||||
resources/system_buttons/sleep_button.cpp
|
resources/system_buttons/sleep_button.cpp
|
||||||
resources/system_buttons/sleep_button.h
|
resources/system_buttons/sleep_button.h
|
||||||
|
resources/system_buttons/system_button_types.h
|
||||||
resources/touch_screen/gesture.cpp
|
resources/touch_screen/gesture.cpp
|
||||||
resources/touch_screen/gesture.h
|
resources/touch_screen/gesture.h
|
||||||
resources/touch_screen/gesture_types.h
|
resources/touch_screen/gesture_types.h
|
||||||
|
@ -422,7 +422,10 @@ struct NpadPowerInfo {
|
|||||||
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
||||||
|
|
||||||
struct LedPattern {
|
struct LedPattern {
|
||||||
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
LedPattern() {
|
||||||
|
raw = 0;
|
||||||
|
}
|
||||||
|
LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
||||||
position1.Assign(light1);
|
position1.Assign(light1);
|
||||||
position2.Assign(light2);
|
position2.Assign(light2);
|
||||||
position3.Assign(light3);
|
position3.Assign(light3);
|
||||||
@ -437,6 +440,16 @@ struct LedPattern {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SleepButtonState {
|
||||||
|
union {
|
||||||
|
u64 raw{};
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
BitField<0, 1, u64> sleep;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SleepButtonState) == 0x8, "SleepButtonState has incorrect size.");
|
||||||
|
|
||||||
struct HomeButtonState {
|
struct HomeButtonState {
|
||||||
union {
|
union {
|
||||||
u64 raw{};
|
u64 raw{};
|
||||||
|
@ -956,17 +956,6 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1,
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
|
|
||||||
if (!IsNpadIdValid(npad_id)) {
|
|
||||||
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
|
|
||||||
return ResultInvalidNpadId;
|
|
||||||
}
|
|
||||||
const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
|
|
||||||
const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device;
|
|
||||||
pattern = controller->GetLedPattern();
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
||||||
Core::HID::NpadIdType npad_id) const {
|
Core::HID::NpadIdType npad_id) const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
@ -97,8 +97,6 @@ public:
|
|||||||
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
||||||
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
||||||
|
|
||||||
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
|
|
||||||
|
|
||||||
Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
||||||
Core::HID::NpadIdType npad_id) const;
|
Core::HID::NpadIdType npad_id) const;
|
||||||
Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,
|
Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "hid_core/resources/mouse/mouse_types.h"
|
#include "hid_core/resources/mouse/mouse_types.h"
|
||||||
#include "hid_core/resources/npad/npad_types.h"
|
#include "hid_core/resources/npad/npad_types.h"
|
||||||
#include "hid_core/resources/ring_lifo.h"
|
#include "hid_core/resources/ring_lifo.h"
|
||||||
|
#include "hid_core/resources/system_buttons/system_button_types.h"
|
||||||
#include "hid_core/resources/touch_screen/touch_types.h"
|
#include "hid_core/resources/touch_screen/touch_types.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
@ -75,24 +76,24 @@ static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000,
|
|||||||
|
|
||||||
// This is nn::hid::detail::HomeButtonSharedMemoryFormat
|
// This is nn::hid::detail::HomeButtonSharedMemoryFormat
|
||||||
struct HomeButtonSharedMemoryFormat {
|
struct HomeButtonSharedMemoryFormat {
|
||||||
CommonHeader header;
|
Lifo<HomeButtonState, HidEntryCount> home_lifo{};
|
||||||
INSERT_PADDING_BYTES(0x1E0);
|
INSERT_PADDING_BYTES(0x48);
|
||||||
};
|
};
|
||||||
static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
|
static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
|
||||||
"HomeButtonSharedMemoryFormat is an invalid size");
|
"HomeButtonSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
// This is nn::hid::detail::SleepButtonSharedMemoryFormat
|
// This is nn::hid::detail::SleepButtonSharedMemoryFormat
|
||||||
struct SleepButtonSharedMemoryFormat {
|
struct SleepButtonSharedMemoryFormat {
|
||||||
CommonHeader header;
|
Lifo<SleepButtonState, HidEntryCount> sleep_lifo{};
|
||||||
INSERT_PADDING_BYTES(0x1E0);
|
INSERT_PADDING_BYTES(0x48);
|
||||||
};
|
};
|
||||||
static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
|
static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
|
||||||
"SleepButtonSharedMemoryFormat is an invalid size");
|
"SleepButtonSharedMemoryFormat is an invalid size");
|
||||||
|
|
||||||
// This is nn::hid::detail::CaptureButtonSharedMemoryFormat
|
// This is nn::hid::detail::CaptureButtonSharedMemoryFormat
|
||||||
struct CaptureButtonSharedMemoryFormat {
|
struct CaptureButtonSharedMemoryFormat {
|
||||||
CommonHeader header;
|
Lifo<CaptureButtonState, HidEntryCount> capture_lifo{};
|
||||||
INSERT_PADDING_BYTES(0x1E0);
|
INSERT_PADDING_BYTES(0x48);
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
|
static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
|
||||||
"CaptureButtonSharedMemoryFormat is an invalid size");
|
"CaptureButtonSharedMemoryFormat is an invalid size");
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
|
#include "hid_core/frontend/emulated_controller.h"
|
||||||
|
#include "hid_core/hid_core.h"
|
||||||
#include "hid_core/resources/applet_resource.h"
|
#include "hid_core/resources/applet_resource.h"
|
||||||
#include "hid_core/resources/shared_memory_format.h"
|
#include "hid_core/resources/shared_memory_format.h"
|
||||||
#include "hid_core/resources/system_buttons/capture_button.h"
|
#include "hid_core/resources/system_buttons/capture_button.h"
|
||||||
@ -17,10 +19,6 @@ void CaptureButton::OnInit() {}
|
|||||||
void CaptureButton::OnRelease() {}
|
void CaptureButton::OnRelease() {}
|
||||||
|
|
||||||
void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!smart_update) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::scoped_lock shared_lock{*shared_mutex};
|
std::scoped_lock shared_lock{*shared_mutex};
|
||||||
const u64 aruid = applet_resource->GetActiveAruid();
|
const u64 aruid = applet_resource->GetActiveAruid();
|
||||||
auto* data = applet_resource->GetAruidData(aruid);
|
auto* data = applet_resource->GetAruidData(aruid);
|
||||||
@ -29,11 +27,21 @@ void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& header = data->shared_memory_format->capture_button.header;
|
auto& shared_memory = data->shared_memory_format->capture_button;
|
||||||
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
|
||||||
header.total_entry_count = 17;
|
if (!IsControllerActivated()) {
|
||||||
header.entry_count = 0;
|
shared_memory.capture_lifo.buffer_count = 0;
|
||||||
header.last_entry_index = 0;
|
shared_memory.capture_lifo.buffer_tail = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& last_entry = shared_memory.capture_lifo.ReadCurrentEntry().state;
|
||||||
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
|
||||||
|
auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||||
|
next_state.buttons.raw = controller->GetHomeButtons().raw;
|
||||||
|
|
||||||
|
shared_memory.capture_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hid_core/resources/controller_base.h"
|
#include "hid_core/resources/controller_base.h"
|
||||||
|
#include "hid_core/resources/system_buttons/system_button_types.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
@ -22,6 +23,6 @@ public:
|
|||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool smart_update{};
|
CaptureButtonState next_state{};
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
|
#include "hid_core/frontend/emulated_controller.h"
|
||||||
|
#include "hid_core/hid_core.h"
|
||||||
#include "hid_core/resources/applet_resource.h"
|
#include "hid_core/resources/applet_resource.h"
|
||||||
#include "hid_core/resources/shared_memory_format.h"
|
#include "hid_core/resources/shared_memory_format.h"
|
||||||
#include "hid_core/resources/system_buttons/home_button.h"
|
#include "hid_core/resources/system_buttons/home_button.h"
|
||||||
@ -17,10 +19,6 @@ void HomeButton::OnInit() {}
|
|||||||
void HomeButton::OnRelease() {}
|
void HomeButton::OnRelease() {}
|
||||||
|
|
||||||
void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!smart_update) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::scoped_lock shared_lock{*shared_mutex};
|
std::scoped_lock shared_lock{*shared_mutex};
|
||||||
const u64 aruid = applet_resource->GetActiveAruid();
|
const u64 aruid = applet_resource->GetActiveAruid();
|
||||||
auto* data = applet_resource->GetAruidData(aruid);
|
auto* data = applet_resource->GetAruidData(aruid);
|
||||||
@ -29,11 +27,21 @@ void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& header = data->shared_memory_format->home_button.header;
|
auto& shared_memory = data->shared_memory_format->home_button;
|
||||||
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
|
||||||
header.total_entry_count = 17;
|
if (!IsControllerActivated()) {
|
||||||
header.entry_count = 0;
|
shared_memory.home_lifo.buffer_count = 0;
|
||||||
header.last_entry_index = 0;
|
shared_memory.home_lifo.buffer_tail = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& last_entry = shared_memory.home_lifo.ReadCurrentEntry().state;
|
||||||
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
|
||||||
|
auto* controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||||
|
next_state.buttons.raw = controller->GetHomeButtons().raw;
|
||||||
|
|
||||||
|
shared_memory.home_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hid_core/resources/controller_base.h"
|
#include "hid_core/resources/controller_base.h"
|
||||||
|
#include "hid_core/resources/system_buttons/system_button_types.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
@ -22,6 +23,6 @@ public:
|
|||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool smart_update{};
|
HomeButtonState next_state{};
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
@ -17,10 +17,6 @@ void SleepButton::OnInit() {}
|
|||||||
void SleepButton::OnRelease() {}
|
void SleepButton::OnRelease() {}
|
||||||
|
|
||||||
void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
||||||
if (!smart_update) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::scoped_lock shared_lock{*shared_mutex};
|
std::scoped_lock shared_lock{*shared_mutex};
|
||||||
const u64 aruid = applet_resource->GetActiveAruid();
|
const u64 aruid = applet_resource->GetActiveAruid();
|
||||||
auto* data = applet_resource->GetAruidData(aruid);
|
auto* data = applet_resource->GetAruidData(aruid);
|
||||||
@ -29,11 +25,20 @@ void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& header = data->shared_memory_format->capture_button.header;
|
auto& shared_memory = data->shared_memory_format->sleep_button;
|
||||||
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
|
||||||
header.total_entry_count = 17;
|
if (!IsControllerActivated()) {
|
||||||
header.entry_count = 0;
|
shared_memory.sleep_lifo.buffer_count = 0;
|
||||||
header.last_entry_index = 0;
|
shared_memory.sleep_lifo.buffer_tail = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& last_entry = shared_memory.sleep_lifo.ReadCurrentEntry().state;
|
||||||
|
next_state.sampling_number = last_entry.sampling_number + 1;
|
||||||
|
|
||||||
|
next_state.buttons.raw = 0;
|
||||||
|
|
||||||
|
shared_memory.sleep_lifo.WriteNextEntry(next_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hid_core/resources/controller_base.h"
|
#include "hid_core/resources/controller_base.h"
|
||||||
|
#include "hid_core/resources/system_buttons/system_button_types.h"
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
@ -22,6 +23,6 @@ public:
|
|||||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool smart_update{};
|
SleepButtonState next_state{};
|
||||||
};
|
};
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
31
src/hid_core/resources/system_buttons/system_button_types.h
Normal file
31
src/hid_core/resources/system_buttons/system_button_types.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
|
||||||
|
// This is nn::hid::system::SleepButtonState
|
||||||
|
struct SleepButtonState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
Core::HID::SleepButtonState buttons;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SleepButtonState) == 0x10, "SleepButtonState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::system::HomeButtonState
|
||||||
|
struct HomeButtonState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
Core::HID::HomeButtonState buttons;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(HomeButtonState) == 0x10, "HomeButtonState is an invalid size");
|
||||||
|
|
||||||
|
// This is nn::hid::system::SleepButtonState
|
||||||
|
struct CaptureButtonState {
|
||||||
|
s64 sampling_number{};
|
||||||
|
Core::HID::CaptureButtonState buttons;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CaptureButtonState) == 0x10, "CaptureButtonState is an invalid size");
|
||||||
|
|
||||||
|
} // namespace Service::HID
|
@ -28,7 +28,7 @@ void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& header = data->shared_memory_format->capture_button.header;
|
auto& header = data->shared_memory_format->unique_pad.header;
|
||||||
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
header.timestamp = core_timing.GetGlobalTimeNs().count();
|
||||||
header.total_entry_count = 17;
|
header.total_entry_count = 17;
|
||||||
header.entry_count = 0;
|
header.entry_count = 0;
|
||||||
|
@ -302,7 +302,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
|
|||||||
|
|
||||||
add_dependencies(video_core host_shaders)
|
add_dependencies(video_core host_shaders)
|
||||||
target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
|
target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
|
||||||
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
|
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator)
|
||||||
|
|
||||||
if (ENABLE_NSIGHT_AFTERMATH)
|
if (ENABLE_NSIGHT_AFTERMATH)
|
||||||
if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
|
if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
|
||||||
|
@ -243,12 +243,10 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
|
|||||||
const u64 size_in_bytes{Tegra::Texture::CalculateSize(
|
const u64 size_in_bytes{Tegra::Texture::CalculateSize(
|
||||||
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
|
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
|
||||||
const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
|
const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
|
||||||
if (host_ptr != nullptr) {
|
const std::span<const u8> input_data(host_ptr, size_in_bytes);
|
||||||
const std::span<const u8> input_data(host_ptr, size_in_bytes);
|
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
|
||||||
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
|
framebuffer.width, framebuffer.height, 1, block_height_log2,
|
||||||
framebuffer.width, framebuffer.height, 1,
|
0);
|
||||||
block_height_log2, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
|
||||||
|
@ -230,11 +230,9 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
|||||||
const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
|
const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
|
||||||
framebuffer.stride, framebuffer.height,
|
framebuffer.stride, framebuffer.height,
|
||||||
1, block_height_log2, 0)};
|
1, block_height_log2, 0)};
|
||||||
if (host_ptr != nullptr) {
|
Tegra::Texture::UnswizzleTexture(
|
||||||
Tegra::Texture::UnswizzleTexture(
|
mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size),
|
||||||
mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size),
|
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
|
||||||
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const VkBufferImageCopy copy{
|
const VkBufferImageCopy copy{
|
||||||
.bufferOffset = image_offset,
|
.bufferOffset = image_offset,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
|
#include "video_core/vulkan_common/vk_enum_string_helper.h"
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
#include "vulkan/vulkan_core.h"
|
#include "vulkan/vulkan_core.h"
|
||||||
@ -151,7 +152,7 @@ bool Swapchain::AcquireNextImage() {
|
|||||||
vk::Check(result);
|
vk::Check(result);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result));
|
LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", string_VkResult(result));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +188,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
|
|||||||
vk::Check(result);
|
vk::Check(result);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result));
|
LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", string_VkResult(result));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++frame_index;
|
++frame_index;
|
||||||
|
@ -1431,7 +1431,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu);
|
ForEachSparseImageInRegion(channel_state->gpu_memory.GetID(), gpu_addr, size_bytes, region_check_gpu);
|
||||||
|
|
||||||
bool can_rescale = info.rescaleable;
|
bool can_rescale = info.rescaleable;
|
||||||
bool any_rescaled = false;
|
bool any_rescaled = false;
|
||||||
@ -1842,7 +1842,7 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
|
|||||||
if (!storage_id) {
|
if (!storage_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& gpu_page_table = gpu_page_table_storage[*storage_id];
|
auto& gpu_page_table = gpu_page_table_storage[*storage_id * 2];
|
||||||
ForEachGPUPage(gpu_addr, size,
|
ForEachGPUPage(gpu_addr, size,
|
||||||
[this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) {
|
[this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) {
|
||||||
const auto it = gpu_page_table.find(page);
|
const auto it = gpu_page_table.find(page);
|
||||||
@ -1882,11 +1882,17 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func) {
|
void TextureCache<P>::ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size,
|
||||||
|
Func&& func) {
|
||||||
using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
|
using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
|
||||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||||
boost::container::small_vector<ImageId, 8> images;
|
boost::container::small_vector<ImageId, 8> images;
|
||||||
ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) {
|
auto storage_id = getStorageID(as_id);
|
||||||
|
if (!storage_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& sparse_page_table = gpu_page_table_storage[*storage_id * 2 + 1];
|
||||||
|
ForEachGPUPage(gpu_addr, size, [this, &sparse_page_table, &images, gpu_addr, size, func](u64 page) {
|
||||||
const auto it = sparse_page_table.find(page);
|
const auto it = sparse_page_table.find(page);
|
||||||
if (it == sparse_page_table.end()) {
|
if (it == sparse_page_table.end()) {
|
||||||
if constexpr (BOOL_BREAK) {
|
if constexpr (BOOL_BREAK) {
|
||||||
@ -1989,7 +1995,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
|
|||||||
});
|
});
|
||||||
sparse_views.emplace(image_id, std::move(sparse_maps));
|
sparse_views.emplace(image_id, std::move(sparse_maps));
|
||||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
|
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
|
||||||
[this, image_id](u64 page) { sparse_page_table[page].push_back(image_id); });
|
[this, image_id](u64 page) { (*channel_state->sparse_page_table)[page].push_back(image_id); });
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
@ -2042,7 +2048,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
|
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
|
||||||
clear_page_table(page, sparse_page_table);
|
clear_page_table(page, (*channel_state->sparse_page_table));
|
||||||
});
|
});
|
||||||
auto it = sparse_views.find(image_id);
|
auto it = sparse_views.find(image_id);
|
||||||
ASSERT(it != sparse_views.end());
|
ASSERT(it != sparse_views.end());
|
||||||
@ -2496,13 +2502,15 @@ void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel
|
|||||||
const auto it = channel_map.find(channel.bind_id);
|
const auto it = channel_map.find(channel.bind_id);
|
||||||
auto* this_state = &channel_storage[it->second];
|
auto* this_state = &channel_storage[it->second];
|
||||||
const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
|
const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
|
||||||
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id];
|
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2];
|
||||||
|
this_state->sparse_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2 + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bind a channel for execution.
|
/// Bind a channel for execution.
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
|
void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
|
||||||
gpu_page_table_storage.emplace_back();
|
gpu_page_table_storage.emplace_back();
|
||||||
|
gpu_page_table_storage.emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
@ -86,6 +86,7 @@ public:
|
|||||||
std::unordered_map<TSCEntry, SamplerId> samplers;
|
std::unordered_map<TSCEntry, SamplerId> samplers;
|
||||||
|
|
||||||
TextureCacheGPUMap* gpu_page_table;
|
TextureCacheGPUMap* gpu_page_table;
|
||||||
|
TextureCacheGPUMap* sparse_page_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
@ -357,7 +358,7 @@ private:
|
|||||||
void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func);
|
void ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||||
|
|
||||||
/// Iterates over all the images in a region calling func
|
/// Iterates over all the images in a region calling func
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
@ -431,7 +432,6 @@ private:
|
|||||||
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
|
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
|
||||||
|
|
||||||
std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
|
std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
|
||||||
std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table;
|
|
||||||
std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
|
std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
|
||||||
|
|
||||||
DAddr virtual_invalid_space{};
|
DAddr virtual_invalid_space{};
|
||||||
|
8
src/video_core/vulkan_common/vk_enum_string_helper.h
Normal file
8
src/video_core/vulkan_common/vk_enum_string_helper.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "video_core/vulkan_common/vulkan.h"
|
||||||
|
|
||||||
|
#include <vulkan/vk_enum_string_helper.h>
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "video_core/vulkan_common/vk_enum_string_helper.h"
|
||||||
#include "video_core/vulkan_common/vma.h"
|
#include "video_core/vulkan_common/vma.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
@ -298,109 +299,7 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* Exception::what() const noexcept {
|
const char* Exception::what() const noexcept {
|
||||||
return ToString(result);
|
return string_VkResult(result);
|
||||||
}
|
|
||||||
|
|
||||||
const char* ToString(VkResult result) noexcept {
|
|
||||||
switch (result) {
|
|
||||||
case VkResult::VK_SUCCESS:
|
|
||||||
return "VK_SUCCESS";
|
|
||||||
case VkResult::VK_NOT_READY:
|
|
||||||
return "VK_NOT_READY";
|
|
||||||
case VkResult::VK_TIMEOUT:
|
|
||||||
return "VK_TIMEOUT";
|
|
||||||
case VkResult::VK_EVENT_SET:
|
|
||||||
return "VK_EVENT_SET";
|
|
||||||
case VkResult::VK_EVENT_RESET:
|
|
||||||
return "VK_EVENT_RESET";
|
|
||||||
case VkResult::VK_INCOMPLETE:
|
|
||||||
return "VK_INCOMPLETE";
|
|
||||||
case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY:
|
|
||||||
return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
|
||||||
case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
|
||||||
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
|
||||||
case VkResult::VK_ERROR_INITIALIZATION_FAILED:
|
|
||||||
return "VK_ERROR_INITIALIZATION_FAILED";
|
|
||||||
case VkResult::VK_ERROR_DEVICE_LOST:
|
|
||||||
return "VK_ERROR_DEVICE_LOST";
|
|
||||||
case VkResult::VK_ERROR_MEMORY_MAP_FAILED:
|
|
||||||
return "VK_ERROR_MEMORY_MAP_FAILED";
|
|
||||||
case VkResult::VK_ERROR_LAYER_NOT_PRESENT:
|
|
||||||
return "VK_ERROR_LAYER_NOT_PRESENT";
|
|
||||||
case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT:
|
|
||||||
return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
|
||||||
case VkResult::VK_ERROR_FEATURE_NOT_PRESENT:
|
|
||||||
return "VK_ERROR_FEATURE_NOT_PRESENT";
|
|
||||||
case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER:
|
|
||||||
return "VK_ERROR_INCOMPATIBLE_DRIVER";
|
|
||||||
case VkResult::VK_ERROR_TOO_MANY_OBJECTS:
|
|
||||||
return "VK_ERROR_TOO_MANY_OBJECTS";
|
|
||||||
case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED:
|
|
||||||
return "VK_ERROR_FORMAT_NOT_SUPPORTED";
|
|
||||||
case VkResult::VK_ERROR_FRAGMENTED_POOL:
|
|
||||||
return "VK_ERROR_FRAGMENTED_POOL";
|
|
||||||
case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY:
|
|
||||||
return "VK_ERROR_OUT_OF_POOL_MEMORY";
|
|
||||||
case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE:
|
|
||||||
return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
|
|
||||||
case VkResult::VK_ERROR_SURFACE_LOST_KHR:
|
|
||||||
return "VK_ERROR_SURFACE_LOST_KHR";
|
|
||||||
case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
|
||||||
return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
|
|
||||||
case VkResult::VK_SUBOPTIMAL_KHR:
|
|
||||||
return "VK_SUBOPTIMAL_KHR";
|
|
||||||
case VkResult::VK_ERROR_OUT_OF_DATE_KHR:
|
|
||||||
return "VK_ERROR_OUT_OF_DATE_KHR";
|
|
||||||
case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
|
||||||
return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
|
|
||||||
case VkResult::VK_ERROR_VALIDATION_FAILED_EXT:
|
|
||||||
return "VK_ERROR_VALIDATION_FAILED_EXT";
|
|
||||||
case VkResult::VK_ERROR_INVALID_SHADER_NV:
|
|
||||||
return "VK_ERROR_INVALID_SHADER_NV";
|
|
||||||
case VkResult::VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:
|
|
||||||
return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
|
|
||||||
case VkResult::VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:
|
|
||||||
return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
|
|
||||||
case VkResult::VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR:
|
|
||||||
return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
|
|
||||||
case VkResult::VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR:
|
|
||||||
return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
|
|
||||||
case VkResult::VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR:
|
|
||||||
return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
|
|
||||||
case VkResult::VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR:
|
|
||||||
return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
|
|
||||||
case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
|
|
||||||
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
|
|
||||||
case VkResult::VK_ERROR_FRAGMENTATION_EXT:
|
|
||||||
return "VK_ERROR_FRAGMENTATION_EXT";
|
|
||||||
case VkResult::VK_ERROR_NOT_PERMITTED_EXT:
|
|
||||||
return "VK_ERROR_NOT_PERMITTED_EXT";
|
|
||||||
case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
|
|
||||||
return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";
|
|
||||||
case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
|
|
||||||
return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
|
|
||||||
case VkResult::VK_ERROR_UNKNOWN:
|
|
||||||
return "VK_ERROR_UNKNOWN";
|
|
||||||
case VkResult::VK_THREAD_IDLE_KHR:
|
|
||||||
return "VK_THREAD_IDLE_KHR";
|
|
||||||
case VkResult::VK_THREAD_DONE_KHR:
|
|
||||||
return "VK_THREAD_DONE_KHR";
|
|
||||||
case VkResult::VK_OPERATION_DEFERRED_KHR:
|
|
||||||
return "VK_OPERATION_DEFERRED_KHR";
|
|
||||||
case VkResult::VK_OPERATION_NOT_DEFERRED_KHR:
|
|
||||||
return "VK_OPERATION_NOT_DEFERRED_KHR";
|
|
||||||
case VkResult::VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:
|
|
||||||
return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR";
|
|
||||||
case VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT:
|
|
||||||
return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
|
|
||||||
case VkResult::VK_RESULT_MAX_ENUM:
|
|
||||||
return "VK_RESULT_MAX_ENUM";
|
|
||||||
case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT:
|
|
||||||
return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
|
|
||||||
case VkResult::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
|
|
||||||
return "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT";
|
|
||||||
}
|
|
||||||
return "Unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
|
void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
|
||||||
@ -1067,7 +966,7 @@ u32 AvailableVersion(const InstanceDispatch& dld) noexcept {
|
|||||||
u32 version;
|
u32 version;
|
||||||
if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) {
|
if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) {
|
||||||
LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1",
|
LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1",
|
||||||
ToString(result));
|
string_VkResult(result));
|
||||||
return VK_API_VERSION_1_1;
|
return VK_API_VERSION_1_1;
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
|
@ -125,9 +125,6 @@ private:
|
|||||||
VkResult result;
|
VkResult result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Converts a VkResult enum into a rodata string
|
|
||||||
const char* ToString(VkResult) noexcept;
|
|
||||||
|
|
||||||
/// Throws a Vulkan exception if result is not success.
|
/// Throws a Vulkan exception if result is not success.
|
||||||
inline void Check(VkResult result) {
|
inline void Check(VkResult result) {
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
#include "audio_core/sink/sink.h"
|
#include "audio_core/sink/sink.h"
|
||||||
#include "audio_core/sink/sink_details.h"
|
#include "audio_core/sink/sink_details.h"
|
||||||
@ -67,19 +68,99 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
|
|||||||
|
|
||||||
hold.emplace(std::pair{setting->Id(), widget});
|
hold.emplace(std::pair{setting->Id(), widget});
|
||||||
|
|
||||||
|
auto global_sink_match = [this] {
|
||||||
|
return static_cast<Settings::AudioEngine>(sink_combo_box->currentIndex()) ==
|
||||||
|
Settings::values.sink_id.GetValue(true);
|
||||||
|
};
|
||||||
if (setting->Id() == Settings::values.sink_id.Id()) {
|
if (setting->Id() == Settings::values.sink_id.Id()) {
|
||||||
// TODO (lat9nq): Let the system manage sink_id
|
// TODO (lat9nq): Let the system manage sink_id
|
||||||
sink_combo_box = widget->combobox;
|
sink_combo_box = widget->combobox;
|
||||||
InitializeAudioSinkComboBox();
|
InitializeAudioSinkComboBox();
|
||||||
|
|
||||||
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
&ConfigureAudio::UpdateAudioDevices);
|
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
|
&ConfigureAudio::UpdateAudioDevices);
|
||||||
|
} else {
|
||||||
|
restore_sink_button = ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||||
|
Settings::values.sink_id.UsingGlobal(), widget);
|
||||||
|
widget->layout()->addWidget(restore_sink_button);
|
||||||
|
connect(restore_sink_button, &QAbstractButton::clicked, [this](bool) {
|
||||||
|
Settings::values.sink_id.SetGlobal(true);
|
||||||
|
const int sink_index = static_cast<int>(Settings::values.sink_id.GetValue());
|
||||||
|
sink_combo_box->setCurrentIndex(sink_index);
|
||||||
|
ConfigureAudio::UpdateAudioDevices(sink_index);
|
||||||
|
Settings::values.audio_output_device_id.SetGlobal(true);
|
||||||
|
Settings::values.audio_input_device_id.SetGlobal(true);
|
||||||
|
restore_sink_button->setVisible(false);
|
||||||
|
});
|
||||||
|
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||||
|
[this, global_sink_match](const int slot) {
|
||||||
|
Settings::values.sink_id.SetGlobal(false);
|
||||||
|
Settings::values.audio_output_device_id.SetGlobal(false);
|
||||||
|
Settings::values.audio_input_device_id.SetGlobal(false);
|
||||||
|
|
||||||
|
restore_sink_button->setVisible(true);
|
||||||
|
restore_sink_button->setEnabled(true);
|
||||||
|
output_device_combo_box->setCurrentIndex(0);
|
||||||
|
restore_output_device_button->setVisible(true);
|
||||||
|
restore_output_device_button->setEnabled(global_sink_match());
|
||||||
|
input_device_combo_box->setCurrentIndex(0);
|
||||||
|
restore_input_device_button->setVisible(true);
|
||||||
|
restore_input_device_button->setEnabled(global_sink_match());
|
||||||
|
ConfigureAudio::UpdateAudioDevices(slot);
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (setting->Id() == Settings::values.audio_output_device_id.Id()) {
|
} else if (setting->Id() == Settings::values.audio_output_device_id.Id()) {
|
||||||
// Keep track of output (and input) device comboboxes to populate them with system
|
// Keep track of output (and input) device comboboxes to populate them with system
|
||||||
// devices, which are determined at run time
|
// devices, which are determined at run time
|
||||||
output_device_combo_box = widget->combobox;
|
output_device_combo_box = widget->combobox;
|
||||||
|
|
||||||
|
if (!Settings::IsConfiguringGlobal()) {
|
||||||
|
restore_output_device_button =
|
||||||
|
ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||||
|
Settings::values.audio_output_device_id.UsingGlobal(), widget);
|
||||||
|
restore_output_device_button->setEnabled(global_sink_match());
|
||||||
|
restore_output_device_button->setVisible(
|
||||||
|
!Settings::values.audio_output_device_id.UsingGlobal());
|
||||||
|
widget->layout()->addWidget(restore_output_device_button);
|
||||||
|
connect(restore_output_device_button, &QAbstractButton::clicked, [this](bool) {
|
||||||
|
Settings::values.audio_output_device_id.SetGlobal(true);
|
||||||
|
SetOutputDevicesFromDeviceID();
|
||||||
|
restore_output_device_button->setVisible(false);
|
||||||
|
});
|
||||||
|
connect(output_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||||
|
[this, global_sink_match](int) {
|
||||||
|
if (updating_devices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Settings::values.audio_output_device_id.SetGlobal(false);
|
||||||
|
restore_output_device_button->setVisible(true);
|
||||||
|
restore_output_device_button->setEnabled(global_sink_match());
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (setting->Id() == Settings::values.audio_input_device_id.Id()) {
|
} else if (setting->Id() == Settings::values.audio_input_device_id.Id()) {
|
||||||
input_device_combo_box = widget->combobox;
|
input_device_combo_box = widget->combobox;
|
||||||
|
|
||||||
|
if (!Settings::IsConfiguringGlobal()) {
|
||||||
|
restore_input_device_button =
|
||||||
|
ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||||
|
Settings::values.audio_input_device_id.UsingGlobal(), widget);
|
||||||
|
widget->layout()->addWidget(restore_input_device_button);
|
||||||
|
connect(restore_input_device_button, &QAbstractButton::clicked, [this](bool) {
|
||||||
|
Settings::values.audio_input_device_id.SetGlobal(true);
|
||||||
|
SetInputDevicesFromDeviceID();
|
||||||
|
restore_input_device_button->setVisible(false);
|
||||||
|
});
|
||||||
|
connect(input_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||||
|
[this, global_sink_match](int) {
|
||||||
|
if (updating_devices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Settings::values.audio_input_device_id.SetGlobal(false);
|
||||||
|
restore_input_device_button->setVisible(true);
|
||||||
|
restore_input_device_button->setEnabled(global_sink_match());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,16 +170,13 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetConfiguration() {
|
void ConfigureAudio::SetConfiguration() {
|
||||||
if (!Settings::IsConfiguringGlobal()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetOutputSinkFromSinkID();
|
SetOutputSinkFromSinkID();
|
||||||
|
|
||||||
// The device list cannot be pre-populated (nor listed) until the output sink is known.
|
// The device list cannot be pre-populated (nor listed) until the output sink is known.
|
||||||
UpdateAudioDevices(sink_combo_box->currentIndex());
|
UpdateAudioDevices(sink_combo_box->currentIndex());
|
||||||
|
|
||||||
SetAudioDevicesFromDeviceID();
|
SetOutputDevicesFromDeviceID();
|
||||||
|
SetInputDevicesFromDeviceID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
||||||
@ -116,8 +194,8 @@ void ConfigureAudio::SetOutputSinkFromSinkID() {
|
|||||||
sink_combo_box->setCurrentIndex(new_sink_index);
|
sink_combo_box->setCurrentIndex(new_sink_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
void ConfigureAudio::SetOutputDevicesFromDeviceID() {
|
||||||
int new_device_index = -1;
|
int new_device_index = 0;
|
||||||
|
|
||||||
const QString output_device_id =
|
const QString output_device_id =
|
||||||
QString::fromStdString(Settings::values.audio_output_device_id.GetValue());
|
QString::fromStdString(Settings::values.audio_output_device_id.GetValue());
|
||||||
@ -129,8 +207,10 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output_device_combo_box->setCurrentIndex(new_device_index);
|
output_device_combo_box->setCurrentIndex(new_device_index);
|
||||||
|
}
|
||||||
|
|
||||||
new_device_index = -1;
|
void ConfigureAudio::SetInputDevicesFromDeviceID() {
|
||||||
|
int new_device_index = 0;
|
||||||
const QString input_device_id =
|
const QString input_device_id =
|
||||||
QString::fromStdString(Settings::values.audio_input_device_id.GetValue());
|
QString::fromStdString(Settings::values.audio_input_device_id.GetValue());
|
||||||
for (int index = 0; index < input_device_combo_box->count(); index++) {
|
for (int index = 0; index < input_device_combo_box->count(); index++) {
|
||||||
@ -149,15 +229,12 @@ void ConfigureAudio::ApplyConfiguration() {
|
|||||||
apply_func(is_powered_on);
|
apply_func(is_powered_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
Settings::values.sink_id.LoadString(
|
||||||
Settings::values.sink_id.LoadString(
|
sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
|
||||||
sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
|
Settings::values.audio_output_device_id.SetValue(
|
||||||
Settings::values.audio_output_device_id.SetValue(
|
output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString());
|
||||||
output_device_combo_box->itemText(output_device_combo_box->currentIndex())
|
Settings::values.audio_input_device_id.SetValue(
|
||||||
.toStdString());
|
input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString());
|
||||||
Settings::values.audio_input_device_id.SetValue(
|
|
||||||
input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::changeEvent(QEvent* event) {
|
void ConfigureAudio::changeEvent(QEvent* event) {
|
||||||
@ -169,6 +246,7 @@ void ConfigureAudio::changeEvent(QEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
||||||
|
updating_devices = true;
|
||||||
output_device_combo_box->clear();
|
output_device_combo_box->clear();
|
||||||
output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
||||||
|
|
||||||
@ -183,6 +261,7 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
|||||||
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) {
|
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) {
|
||||||
input_device_combo_box->addItem(QString::fromStdString(device));
|
input_device_combo_box->addItem(QString::fromStdString(device));
|
||||||
}
|
}
|
||||||
|
updating_devices = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::InitializeAudioSinkComboBox() {
|
void ConfigureAudio::InitializeAudioSinkComboBox() {
|
||||||
|
@ -45,7 +45,8 @@ private:
|
|||||||
void UpdateAudioDevices(int sink_index);
|
void UpdateAudioDevices(int sink_index);
|
||||||
|
|
||||||
void SetOutputSinkFromSinkID();
|
void SetOutputSinkFromSinkID();
|
||||||
void SetAudioDevicesFromDeviceID();
|
void SetOutputDevicesFromDeviceID();
|
||||||
|
void SetInputDevicesFromDeviceID();
|
||||||
|
|
||||||
void Setup(const ConfigurationShared::Builder& builder);
|
void Setup(const ConfigurationShared::Builder& builder);
|
||||||
|
|
||||||
@ -55,7 +56,11 @@ private:
|
|||||||
|
|
||||||
std::vector<std::function<void(bool)>> apply_funcs{};
|
std::vector<std::function<void(bool)>> apply_funcs{};
|
||||||
|
|
||||||
|
bool updating_devices = false;
|
||||||
QComboBox* sink_combo_box;
|
QComboBox* sink_combo_box;
|
||||||
|
QPushButton* restore_sink_button;
|
||||||
QComboBox* output_device_combo_box;
|
QComboBox* output_device_combo_box;
|
||||||
|
QPushButton* restore_output_device_button;
|
||||||
QComboBox* input_device_combo_box;
|
QComboBox* input_device_combo_box;
|
||||||
|
QPushButton* restore_input_device_button;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user