Compare commits

...

30 Commits

Author SHA1 Message Date
german77
8e93537266 service: am: Focus state changed goes last 2024-01-28 22:02:01 -06:00
liamwhite
6a2532fe17 Merge pull request #12555 from flodavid/fix-gamemode-setting
Save gamemode configuration and add per-game config
2024-01-28 15:02:34 -05:00
liamwhite
3655115105 Merge pull request #12821 from merryhime/atomic_ops
atomic_ops: Reduce code duplication with templates
2024-01-28 15:02:28 -05:00
liamwhite
5561a08d59 Merge pull request #12831 from Kelebek1/audren_multi
Use the input process handle to get the correct application's memory
2024-01-28 15:02:22 -05:00
liamwhite
e687ca8735 Merge pull request #12833 from merryhime/vsync-crash
configure_graphics: Avoid crash when vsync_mode_combobox is empty
2024-01-28 15:02:15 -05:00
Merry
0bf46cb1ee configure_graphics: Avoid crash when vsync_mode_combobox is empty (occurs when renderer backend is Null) 2024-01-28 19:14:38 +00:00
liamwhite
72c897c49d Merge pull request #12826 from t895/system-driver-version
android: Show system driver information
2024-01-28 11:57:58 -05:00
liamwhite
077a50a547 Merge pull request #12825 from liamwhite/why
kernel: clear pinned waiter list on unpin
2024-01-28 11:57:53 -05:00
liamwhite
820f1c8a16 Merge pull request #12823 from german77/set-audio
service: set: Implement more Qlaunch Settings
2024-01-28 11:57:47 -05:00
liamwhite
b163757e1f Merge pull request #12802 from german77/mii_interface
service: mii: Migrate service to new interface
2024-01-28 11:57:40 -05:00
german77
b75401a2cb service: set: Increase settings version 2024-01-28 09:32:54 -06:00
german77
12e7ee2357 service: set: Implement more Qlaunch Settings 2024-01-28 09:32:46 -06:00
Charles Lombardo
3ec41503e3 Merge pull request #12827 from t895/focus-color
android: Disable focus on loading card
2024-01-28 08:52:57 -05:00
t895
c770af9b12 android: Disable focus on loading card
Additionally de-emphasize the ripple that I can't disable
2024-01-28 00:25:07 -05:00
t895
2d8f80b65e android: Show system driver information 2024-01-27 23:59:02 -05:00
Liam
6c4eb2733d kernel: clear pinned waiter list on unpin 2024-01-27 22:53:49 -05:00
liamwhite
d5e8c9d04f Merge pull request #12824 from t895/multi-boot
android: Multi-program app switching
2024-01-27 21:48:54 -05:00
t895
3f1290cee3 android: Multi-program app switching 2024-01-27 20:05:51 -05:00
Merry
5a20d07c21 atomic_ops: Fix MSVC 2024-01-27 21:42:16 +00:00
Merry
9f91d310c6 atomic_ops: Remove volatile qualifier 2024-01-27 21:36:39 +00:00
Merry
6527c0d2fc atomic_ops: Reduce code duplication with templates
Also fixes builds on unusual toolchains where:
- u32 is unsigned int
- u64 is unsigned long long
- uintptr_t is unsigned long
2024-01-27 21:12:12 +00:00
liamwhite
ce2eb6e8ee Merge pull request #12818 from K900/small-fixes
A few small fixes
2024-01-27 12:13:46 -05:00
K900
8b47465586 input: add a missing null pointer check
There's a few other places where the result of GetAruidData is accessed without a null check,
but I couldn't find a code path that hits those.
2024-01-27 17:32:49 +03:00
K900
3065ab0fd8 nx_tzdb: add another safety assertion 2024-01-27 17:28:04 +03:00
K900
a2407a2964 nx_tzdb: check for unpacked directory
Otherwise things get funny if the archive is downloaded, but the unpacking was interrupted.
2024-01-27 17:25:52 +03:00
liamwhite
16b79df836 Merge pull request #12815 from t895/visual-driver-silly
android: Reload global settings on closing emulation
2024-01-27 01:36:26 -05:00
t895
6a4b25699d android: Reload global settings on closing emulation
UI like the driver manager expects the global settings to be loaded when in the MainActivity so we reload global config to properly reset state on exit.
2024-01-26 23:05:02 -05:00
Narr the Reg
c5e88c654e service: mii: Migrate service to new interface 2024-01-26 10:43:34 -06:00
flodavid
e231b8b6f5 yuzu: Add per-game linux gamemode configuration 2024-01-02 21:21:40 +01:00
flodavid
68fe1e3476 fix linux config values not saved 2024-01-02 21:21:40 +01:00
48 changed files with 970 additions and 569 deletions

View File

@@ -32,7 +32,7 @@ set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ARCHIVE})
if ((NOT CAN_BUILD_NX_TZDB OR YUZU_DOWNLOAD_TIME_ZONE_DATA) AND NOT EXISTS ${NX_TZDB_ROMFS_DIR})
set(NX_TZDB_DOWNLOAD_URL "https://github.com/lat9nq/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")

View File

@@ -11,6 +11,10 @@ execute_process(
WORKING_DIRECTORY ${ZONE_PATH}
OUTPUT_VARIABLE FILE_LIST)
if (NOT FILE_LIST)
message(FATAL_ERROR "No timezone files found in directory ${ZONE_PATH}, did the download fail?")
endif()
set(DIRECTORY_NAME ${HEADER_NAME})
set(FILE_DATA "")

View File

@@ -261,7 +261,7 @@ object NativeLibrary {
/**
* Begins emulation.
*/
external fun run(path: String?)
external fun run(path: String?, programIndex: Int = 0)
// Surface Handling
external fun surfaceChanged(surf: Surface?)
@@ -489,6 +489,12 @@ object NativeLibrary {
sEmulationActivity.get()!!.onEmulationStopped(status)
}
@Keep
@JvmStatic
fun onProgramChanged(programIndex: Int) {
sEmulationActivity.get()!!.onProgramChanged(programIndex)
}
/**
* Logs the Yuzu version, Android version and, CPU.
*/

View File

@@ -76,7 +76,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
override fun onDestroy() {
stopForegroundService(this)
emulationViewModel.clear()
super.onDestroy()
}
@@ -446,9 +445,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
}
fun onEmulationStopped(status: Int) {
if (status == 0) {
if (status == 0 && emulationViewModel.programChanged.value == -1) {
finish()
}
emulationViewModel.setEmulationStopped(true)
}
fun onProgramChanged(programIndex: Int) {
emulationViewModel.setProgramChanged(programIndex)
}
private fun startMotionSensorListener() {

View File

@@ -301,6 +301,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
R.id.menu_exit -> {
emulationState.stop()
NativeConfig.reloadGlobalConfig()
emulationViewModel.setIsEmulationStopping(true)
binding.drawerLayout.close()
binding.inGameMenu.requestFocus()
@@ -423,10 +424,38 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
}
launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
emulationViewModel.programChanged.collect {
if (it != 0) {
emulationViewModel.setEmulationStarted(false)
binding.drawerLayout.close()
binding.drawerLayout
.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
ViewUtils.hideView(binding.surfaceInputOverlay)
ViewUtils.showView(binding.loadingIndicator)
}
}
}
}
launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
emulationViewModel.emulationStopped.collect {
if (it && emulationViewModel.programChanged.value != -1) {
if (perfStatsUpdater != null) {
perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
}
emulationState.changeProgram(emulationViewModel.programChanged.value)
emulationViewModel.setProgramChanged(-1)
emulationViewModel.setEmulationStopped(false)
}
}
}
}
}
}
private fun startEmulation() {
private fun startEmulation(programIndex: Int = 0) {
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start()
@@ -434,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
updateScreenLayout()
emulationState.run(emulationActivity!!.isActivityRecreated)
emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
}
}
@@ -832,6 +861,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
) {
private var state: State
private var surface: Surface? = null
lateinit var emulationThread: Thread
init {
// Starting state is stopped.
@@ -877,7 +907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
@Synchronized
fun run(isActivityRecreated: Boolean) {
fun run(isActivityRecreated: Boolean, programIndex: Int = 0) {
if (isActivityRecreated) {
if (NativeLibrary.isRunning()) {
state = State.PAUSED
@@ -888,10 +918,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// If the surface is set, run now. Otherwise, wait for it to get set.
if (surface != null) {
runWithValidSurface()
runWithValidSurface(programIndex)
}
}
@Synchronized
fun changeProgram(programIndex: Int) {
emulationThread.join()
emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.run(gamePath, programIndex)
}, "NativeEmulation")
emulationThread.start()
}
// Surface callbacks
@Synchronized
fun newSurface(surface: Surface?) {
@@ -931,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
private fun runWithValidSurface() {
private fun runWithValidSurface(programIndex: Int = 0) {
NativeLibrary.surfaceChanged(surface)
if (!emulationCanStart.invoke()) {
return
@@ -939,9 +979,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
when (state) {
State.STOPPED -> {
val emulationThread = Thread({
emulationThread = Thread({
Log.debug("[EmulationFragment] Starting emulation thread.")
NativeLibrary.run(gamePath)
NativeLibrary.run(gamePath, programIndex)
}, "NativeEmulation")
emulationThread.start()
}

View File

@@ -66,10 +66,13 @@ class DriverViewModel : ViewModel() {
fun updateDriverList() {
val selectedDriver = GpuDriverHelper.customDriverSettingData
val systemDriverData = GpuDriverHelper.getSystemDriverInfo()
val newDriverList = mutableListOf(
Driver(
selectedDriver == GpuDriverMetadata(),
YuzuApplication.appContext.getString(R.string.system_gpu_driver)
YuzuApplication.appContext.getString(R.string.system_gpu_driver),
systemDriverData?.get(0) ?: "",
systemDriverData?.get(1) ?: ""
)
)
driverData.forEach {

View File

@@ -15,6 +15,12 @@ class EmulationViewModel : ViewModel() {
val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping
private val _isEmulationStopping = MutableStateFlow(false)
private val _emulationStopped = MutableStateFlow(false)
val emulationStopped = _emulationStopped.asStateFlow()
private val _programChanged = MutableStateFlow(-1)
val programChanged = _programChanged.asStateFlow()
val shaderProgress: StateFlow<Int> get() = _shaderProgress
private val _shaderProgress = MutableStateFlow(0)
@@ -35,6 +41,17 @@ class EmulationViewModel : ViewModel() {
_isEmulationStopping.value = value
}
fun setEmulationStopped(value: Boolean) {
if (value) {
_emulationStarted.value = false
}
_emulationStopped.value = value
}
fun setProgramChanged(programIndex: Int) {
_programChanged.value = programIndex
}
fun setShaderProgress(progress: Int) {
_shaderProgress.value = progress
}
@@ -56,20 +73,4 @@ class EmulationViewModel : ViewModel() {
fun setDrawerOpen(value: Boolean) {
_drawerOpen.value = value
}
fun clear() {
setEmulationStarted(false)
setIsEmulationStopping(false)
setShaderProgress(0)
setTotalShaders(0)
setShaderMessage("")
}
companion object {
const val KEY_EMULATION_STARTED = "EmulationStarted"
const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting"
const val KEY_SHADER_PROGRESS = "ShaderProgress"
const val KEY_TOTAL_SHADERS = "TotalShaders"
const val KEY_SHADER_MESSAGE = "ShaderMessage"
}
}

View File

@@ -3,8 +3,10 @@
package org.yuzu.yuzu_emu.utils
import android.graphics.SurfaceTexture
import android.net.Uri
import android.os.Build
import android.view.Surface
import java.io.File
import java.io.IOException
import org.yuzu.yuzu_emu.NativeLibrary
@@ -195,6 +197,11 @@ object GpuDriverHelper {
external fun supportsCustomDriverLoading(): Boolean
external fun getSystemDriverInfo(
surface: Surface = Surface(SurfaceTexture(true)),
hookLibPath: String = GpuDriverHelper.hookLibPath!!
): Array<String>?
// Parse the custom driver metadata to retrieve the name.
val installedCustomDriverData: GpuDriverMetadata
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))

View File

@@ -22,7 +22,7 @@ add_library(yuzu-android SHARED
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers)
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
if (ARCHITECTURE_arm64)
target_link_libraries(yuzu-android PRIVATE adrenotools)

View File

@@ -19,6 +19,7 @@ static jmethodID s_exit_emulation_activity;
static jmethodID s_disk_cache_load_progress;
static jmethodID s_on_emulation_started;
static jmethodID s_on_emulation_stopped;
static jmethodID s_on_program_changed;
static jclass s_game_class;
static jmethodID s_game_constructor;
@@ -123,6 +124,10 @@ jmethodID GetOnEmulationStopped() {
return s_on_emulation_stopped;
}
jmethodID GetOnProgramChanged() {
return s_on_program_changed;
}
jclass GetGameClass() {
return s_game_class;
}
@@ -306,6 +311,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V");
s_on_emulation_stopped =
env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V");
s_on_program_changed =
env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V");
const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game");
s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class));

View File

@@ -19,6 +19,7 @@ jmethodID GetExitEmulationActivity();
jmethodID GetDiskCacheLoadProgress();
jmethodID GetOnEmulationStarted();
jmethodID GetOnEmulationStopped();
jmethodID GetOnProgramChanged();
jclass GetGameClass();
jmethodID GetGameConstructor();

View File

@@ -60,6 +60,9 @@
#include "jni/id_cache.h"
#include "jni/native.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_surface.h"
#define jconst [[maybe_unused]] const auto
#define jauto [[maybe_unused]] auto
@@ -208,7 +211,8 @@ void EmulationSession::InitializeSystem(bool reload) {
m_system.GetFileSystemController().CreateFactories(*m_vfs);
}
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
const std::size_t program_index) {
std::scoped_lock lock(m_mutex);
// Create the render window.
@@ -238,7 +242,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
ConfigureFilesystemProvider(filepath);
// Load the ROM.
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
m_load_result =
m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index);
if (m_load_result != Core::SystemResultStatus::Success) {
return m_load_result;
}
@@ -248,6 +253,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([&] { HaltEmulation(); });
// Register an ExecuteProgram callback such that Core can execute a sub-program
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
m_next_program_index = program_index_;
EmulationSession::GetInstance().HaltEmulation();
});
OnEmulationStarted();
return Core::SystemResultStatus::Success;
}
@@ -255,6 +266,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
void EmulationSession::ShutdownEmulation() {
std::scoped_lock lock(m_mutex);
if (m_next_program_index != -1) {
ChangeProgram(m_next_program_index);
m_next_program_index = -1;
}
m_is_running = false;
// Unload user input.
@@ -402,6 +418,12 @@ void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
static_cast<jint>(result));
}
void EmulationSession::ChangeProgram(std::size_t program_index) {
JNIEnv* env = IDCache::GetEnvForThread();
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(),
static_cast<jint>(program_index));
}
u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
auto program_id_string = GetJString(env, jprogramId);
try {
@@ -411,7 +433,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) {
MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); });
@@ -424,7 +447,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath);
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
if (result != Core::SystemResultStatus::Success) {
return result;
}
@@ -521,6 +544,37 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri
#endif
}
jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
const char* file_redirect_dir_{};
int featureFlags{};
std::string hook_lib_dir = GetJString(env, j_hook_lib_dir);
auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
nullptr, nullptr, file_redirect_dir_, nullptr);
auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
InputCommon::InputSubsystem input_subsystem;
auto m_window = std::make_unique<EmuWindow_Android>(
&input_subsystem, ANativeWindow_fromSurface(env, j_surf), driver_library);
Vulkan::vk::InstanceDispatch dld;
Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
*driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
auto surface = Vulkan::CreateSurface(vk_instance, m_window->GetWindowInfo());
auto device = Vulkan::CreateDevice(vk_instance, dld, *surface);
auto driver_version = device.GetDriverVersion();
auto version_string =
fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
jobjectArray j_driver_info =
env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string));
env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName()));
return j_driver_info;
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
Core::Crypto::KeyManager::Instance().ReloadKeys();
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
@@ -689,11 +743,11 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
Settings::LogSettings();
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz,
jstring j_path) {
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
jint j_program_index) {
const std::string path = GetJString(env, j_path);
const Core::SystemResultStatus result{RunEmulation(path)};
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
if (result != Core::SystemResultStatus::Success) {
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
IDCache::GetExitEmulationActivity(), static_cast<int>(result));

View File

@@ -45,7 +45,8 @@ public:
const Core::PerfStatsResults& PerfStats();
void ConfigureFilesystemProvider(const std::string& filepath);
void InitializeSystem(bool reload);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
const std::size_t program_index = 0);
bool IsHandheldOnly();
void SetDeviceType([[maybe_unused]] int index, int type);
@@ -60,6 +61,7 @@ public:
private:
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
static void OnEmulationStopped(Core::SystemResultStatus result);
static void ChangeProgram(std::size_t program_index);
private:
// Window management
@@ -84,4 +86,7 @@ private:
// Synchronization
std::condition_variable_any m_cv;
mutable std::mutex m_mutex;
// Program index for next boot
std::atomic<s32> m_next_program_index = -1;
};

View File

@@ -34,8 +34,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:focusable="false"
android:defaultFocusHighlightEnabled="false"
android:clickable="false">
android:clickable="false"
app:rippleColor="@android:color/transparent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/loading_layout"

View File

@@ -15,25 +15,34 @@ namespace Common {
#if _MSC_VER
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected);
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual);
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected) {
const u8 result =
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
return result == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected) {
const u16 result =
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
return result == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected) {
const u32 result =
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
return result == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected) {
const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
value, expected);
return result == expected;
@@ -45,29 +54,32 @@ namespace Common {
reinterpret_cast<__int64*>(expected.data())) != 0;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
u8& actual) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u8>(u8* pointer, u8 value, u8 expected, u8& actual) {
actual =
_InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
u16& actual) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u16>(u16* pointer, u16 value, u16 expected,
u16& actual) {
actual =
_InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
u32& actual) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u32>(u32* pointer, u32 value, u32 expected,
u32& actual) {
actual =
_InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
u64& actual) {
template <>
[[nodiscard]] inline bool AtomicCompareAndSwap<u64>(u64* pointer, u64 value, u64 expected,
u64& actual) {
actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value,
expected);
return actual == expected;
@@ -91,23 +103,12 @@ namespace Common {
#else
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) {
unsigned __int128 value_a;
unsigned __int128 expected_a;
std::memcpy(&value_a, value.data(), sizeof(u128));
@@ -115,31 +116,13 @@ namespace Common {
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected,
u8& actual) {
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected,
u16& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected,
u32& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected,
u64& actual) {
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected,
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected,
u128& actual) {
unsigned __int128 value_a;
unsigned __int128 expected_a;
@@ -151,7 +134,7 @@ namespace Common {
return actual_a == expected_a;
}
[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) {
[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) {
unsigned __int128 zeros_a = 0;
unsigned __int128 result_a =
__sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);

View File

@@ -543,7 +543,8 @@ void KThread::Unpin() {
ASSERT(m_parent != nullptr);
// Resume any threads that began waiting on us while we were pinned.
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end();
it = m_pinned_waiter_list.erase(it)) {
it->EndWait(ResultSuccess);
}
}

View File

@@ -931,8 +931,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
// Configure applets to be in foreground state
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
}
ICommonStateGetter::~ICommonStateGetter() {

View File

@@ -59,7 +59,7 @@ void MiiEdit::Initialize() {
break;
}
manager = system.ServiceManager().GetService<Mii::MiiDBModule>("mii:e")->GetMiiManager();
manager = system.ServiceManager().GetService<Mii::IStaticService>("mii:e")->GetMiiManager();
if (manager == nullptr) {
manager = std::make_shared<Mii::MiiManager>();
}

View File

@@ -4,6 +4,8 @@
#include "common/logging/log.h"
#include "core/hle/service/audio/audctl.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h"
namespace Service::Audio {
@@ -19,15 +21,15 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{6, nullptr, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"},
{9, nullptr, "GetAudioOutputMode"},
{10, nullptr, "SetAudioOutputMode"},
{9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"},
{10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"},
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
{14, nullptr, "SetOutputModeSetting"},
{14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"},
{17, nullptr, "SetHeadphoneOutputLevelMode"},
{17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"},
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
@@ -40,7 +42,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{30, nullptr, "SetSpeakerAutoMuteEnabled"},
{30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"},
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"},
@@ -68,6 +70,9 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
// clang-format on
RegisterHandlers(functions);
m_set_sys =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
}
AudCtl::~AudCtl() = default;
@@ -96,6 +101,33 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
rb.Push(target_max_volume);
}
void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
Set::AudioOutputMode output_mode{};
const auto result = m_set_sys->GetAudioOutputMode(output_mode, target);
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.PushEnum(output_mode);
}
void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
const auto result = m_set_sys->SetAudioOutputMode(target, output_mode);
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
}
void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
LOG_WARNING(Audio, "(STUBBED) called");
@@ -106,13 +138,31 @@ void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto value = rp.Pop<u32>();
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
LOG_WARNING(Audio, "(STUBBED) called, value={}", value);
LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(AudioOutputMode::PcmAuto);
rb.PushEnum(Set::AudioOutputMode::ch_7_1);
}
void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
LOG_WARNING(Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
@@ -123,14 +173,28 @@ void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
rb.PushEnum(HeadphoneOutputLevelMode::Normal);
}
void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()};
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
is_speaker_auto_mute_enabled);
const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
}
void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
const bool is_speaker_auto_mute_enabled = false;
bool is_speaker_auto_mute_enabled{};
const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
is_speaker_auto_mute_enabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(result);
rb.Push<u8>(is_speaker_auto_mute_enabled);
}

View File

@@ -9,6 +9,10 @@ namespace Core {
class System;
}
namespace Service::Set {
class ISystemSettingsServer;
}
namespace Service::Audio {
class AudCtl final : public ServiceFramework<AudCtl> {
@@ -17,14 +21,6 @@ public:
~AudCtl() override;
private:
enum class AudioOutputMode {
Invalid,
Pcm1ch,
Pcm2ch,
Pcm6ch,
PcmAuto,
};
enum class ForceMutePolicy {
Disable,
SpeakerMuteOnHeadphoneUnplugged,
@@ -37,10 +33,18 @@ private:
void GetTargetVolumeMin(HLERequestContext& ctx);
void GetTargetVolumeMax(HLERequestContext& ctx);
void GetAudioOutputMode(HLERequestContext& ctx);
void SetAudioOutputMode(HLERequestContext& ctx);
void GetForceMutePolicy(HLERequestContext& ctx);
void GetOutputModeSetting(HLERequestContext& ctx);
void SetOutputModeSetting(HLERequestContext& ctx);
void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
void AcquireTargetNotification(HLERequestContext& ctx);
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
};
} // namespace Service::Audio

View File

@@ -4,15 +4,18 @@
#include <memory>
#include "common/logging/log.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/mii/mii.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/mii_result.h"
#include "core/hle/service/mii/types/char_info.h"
#include "core/hle/service/mii/types/raw_data.h"
#include "core/hle/service/mii/types/store_data.h"
#include "core/hle/service/mii/types/ver3_store_data.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h"
namespace Service::Mii {
@@ -24,549 +27,302 @@ public:
is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IDatabaseService::IsUpdated, "IsUpdated"},
{1, &IDatabaseService::IsFullDatabase, "IsFullDatabase"},
{2, &IDatabaseService::GetCount, "GetCount"},
{3, &IDatabaseService::Get, "Get"},
{4, &IDatabaseService::Get1, "Get1"},
{5, &IDatabaseService::UpdateLatest, "UpdateLatest"},
{6, &IDatabaseService::BuildRandom, "BuildRandom"},
{7, &IDatabaseService::BuildDefault, "BuildDefault"},
{8, &IDatabaseService::Get2, "Get2"},
{9, &IDatabaseService::Get3, "Get3"},
{10, &IDatabaseService::UpdateLatest1, "UpdateLatest1"},
{11, &IDatabaseService::FindIndex, "FindIndex"},
{12, &IDatabaseService::Move, "Move"},
{13, &IDatabaseService::AddOrReplace, "AddOrReplace"},
{14, &IDatabaseService::Delete, "Delete"},
{15, &IDatabaseService::DestroyFile, "DestroyFile"},
{16, &IDatabaseService::DeleteFile, "DeleteFile"},
{17, &IDatabaseService::Format, "Format"},
{0, D<&IDatabaseService::IsUpdated>, "IsUpdated"},
{1, D<&IDatabaseService::IsFullDatabase>, "IsFullDatabase"},
{2, D<&IDatabaseService::GetCount>, "GetCount"},
{3, D<&IDatabaseService::Get>, "Get"},
{4, D<&IDatabaseService::Get1>, "Get1"},
{5, D<&IDatabaseService::UpdateLatest>, "UpdateLatest"},
{6, D<&IDatabaseService::BuildRandom>, "BuildRandom"},
{7, D<&IDatabaseService::BuildDefault>, "BuildDefault"},
{8, D<&IDatabaseService::Get2>, "Get2"},
{9, D<&IDatabaseService::Get3>, "Get3"},
{10, D<&IDatabaseService::UpdateLatest1>, "UpdateLatest1"},
{11, D<&IDatabaseService::FindIndex>, "FindIndex"},
{12, D<&IDatabaseService::Move>, "Move"},
{13, D<&IDatabaseService::AddOrReplace>, "AddOrReplace"},
{14, D<&IDatabaseService::Delete>, "Delete"},
{15, D<&IDatabaseService::DestroyFile>, "DestroyFile"},
{16, D<&IDatabaseService::DeleteFile>, "DeleteFile"},
{17, D<&IDatabaseService::Format>, "Format"},
{18, nullptr, "Import"},
{19, nullptr, "Export"},
{20, &IDatabaseService::IsBrokenDatabaseWithClearFlag, "IsBrokenDatabaseWithClearFlag"},
{21, &IDatabaseService::GetIndex, "GetIndex"},
{22, &IDatabaseService::SetInterfaceVersion, "SetInterfaceVersion"},
{23, &IDatabaseService::Convert, "Convert"},
{24, &IDatabaseService::ConvertCoreDataToCharInfo, "ConvertCoreDataToCharInfo"},
{25, &IDatabaseService::ConvertCharInfoToCoreData, "ConvertCharInfoToCoreData"},
{26, &IDatabaseService::Append, "Append"},
{20, D<&IDatabaseService::IsBrokenDatabaseWithClearFlag>, "IsBrokenDatabaseWithClearFlag"},
{21, D<&IDatabaseService::GetIndex>, "GetIndex"},
{22, D<&IDatabaseService::SetInterfaceVersion>, "SetInterfaceVersion"},
{23, D<&IDatabaseService::Convert>, "Convert"},
{24, D<&IDatabaseService::ConvertCoreDataToCharInfo>, "ConvertCoreDataToCharInfo"},
{25, D<&IDatabaseService::ConvertCharInfoToCoreData>, "ConvertCharInfoToCoreData"},
{26, D<&IDatabaseService::Append>, "Append"},
};
// clang-format on
RegisterHandlers(functions);
m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>(
"set:sys", true);
manager->Initialize(metadata);
}
private:
void IsUpdated(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
Result IsUpdated(Out<bool> out_is_updated, SourceFlag source_flag) {
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
const bool is_updated = manager->IsUpdated(metadata, source_flag);
*out_is_updated = manager->IsUpdated(metadata, source_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_updated);
R_SUCCEED();
}
void IsFullDatabase(HLERequestContext& ctx) {
Result IsFullDatabase(Out<bool> out_is_full_database) {
LOG_DEBUG(Service_Mii, "called");
const bool is_full_database = manager->IsFullDatabase();
*out_is_full_database = manager->IsFullDatabase();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_full_database);
R_SUCCEED();
}
void GetCount(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
Result GetCount(Out<u32> out_mii_count, SourceFlag source_flag) {
*out_mii_count = manager->GetCount(metadata, source_flag);
const u32 mii_count = manager->GetCount(metadata, source_flag);
LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
*out_mii_count);
LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, mii_count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(mii_count);
R_SUCCEED();
}
void Get(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()};
Result Get(Out<u32> out_mii_count, SourceFlag source_flag,
OutArray<CharInfoElement, BufferAttr_HipcMapAlias> char_info_element_buffer) {
const auto result =
manager->Get(metadata, char_info_element_buffer, *out_mii_count, source_flag);
u32 mii_count{};
std::vector<CharInfoElement> char_info_elements(output_size);
const auto result = manager->Get(metadata, char_info_elements, mii_count, source_flag);
LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
*out_mii_count);
if (mii_count != 0) {
ctx.WriteBuffer(char_info_elements);
}
LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
output_size, mii_count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push(mii_count);
R_RETURN(result);
}
void Get1(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
Result Get1(Out<u32> out_mii_count, SourceFlag source_flag,
OutArray<CharInfo, BufferAttr_HipcMapAlias> char_info_buffer) {
const auto result = manager->Get(metadata, char_info_buffer, *out_mii_count, source_flag);
u32 mii_count{};
std::vector<CharInfo> char_info(output_size);
const auto result = manager->Get(metadata, char_info, mii_count, source_flag);
LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
*out_mii_count);
if (mii_count != 0) {
ctx.WriteBuffer(char_info);
}
LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
output_size, mii_count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push(mii_count);
R_RETURN(result);
}
void UpdateLatest(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto char_info{rp.PopRaw<CharInfo>()};
const auto source_flag{rp.PopRaw<SourceFlag>()};
Result UpdateLatest(Out<CharInfo> out_char_info, CharInfo& char_info, SourceFlag source_flag) {
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
CharInfo new_char_info{};
const auto result = manager->UpdateLatest(metadata, new_char_info, char_info, source_flag);
if (result.IsFailure()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
return;
}
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess);
rb.PushRaw(new_char_info);
R_RETURN(manager->UpdateLatest(metadata, *out_char_info, char_info, source_flag));
}
void BuildRandom(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto age{rp.PopRaw<Age>()};
const auto gender{rp.PopRaw<Gender>()};
const auto race{rp.PopRaw<Race>()};
Result BuildRandom(Out<CharInfo> out_char_info, Age age, Gender gender, Race race) {
LOG_DEBUG(Service_Mii, "called with age={}, gender={}, race={}", age, gender, race);
if (age > Age::All) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultInvalidArgument);
return;
}
R_UNLESS(age <= Age::All, ResultInvalidArgument);
R_UNLESS(gender <= Gender::All, ResultInvalidArgument);
R_UNLESS(race <= Race::All, ResultInvalidArgument);
if (gender > Gender::All) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultInvalidArgument);
return;
}
manager->BuildRandom(*out_char_info, age, gender, race);
if (race > Race::All) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultInvalidArgument);
return;
}
CharInfo char_info{};
manager->BuildRandom(char_info, age, gender, race);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess);
rb.PushRaw(char_info);
R_SUCCEED();
}
void BuildDefault(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto index{rp.Pop<u32>()};
Result BuildDefault(Out<CharInfo> out_char_info, s32 index) {
LOG_DEBUG(Service_Mii, "called with index={}", index);
R_UNLESS(index < static_cast<s32>(RawData::DefaultMii.size()), ResultInvalidArgument);
if (index > 5) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultInvalidArgument);
return;
}
manager->BuildDefault(*out_char_info, index);
CharInfo char_info{};
manager->BuildDefault(char_info, index);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess);
rb.PushRaw(char_info);
R_SUCCEED();
}
void Get2(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
const auto output_size{ctx.GetWriteBufferNumElements<StoreDataElement>()};
Result Get2(Out<u32> out_mii_count, SourceFlag source_flag,
OutArray<StoreDataElement, BufferAttr_HipcMapAlias> store_data_element_buffer) {
const auto result =
manager->Get(metadata, store_data_element_buffer, *out_mii_count, source_flag);
u32 mii_count{};
std::vector<StoreDataElement> store_data_elements(output_size);
const auto result = manager->Get(metadata, store_data_elements, mii_count, source_flag);
LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
*out_mii_count);
if (mii_count != 0) {
ctx.WriteBuffer(store_data_elements);
}
LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
output_size, mii_count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push(mii_count);
R_RETURN(result);
}
void Get3(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto source_flag{rp.PopRaw<SourceFlag>()};
const auto output_size{ctx.GetWriteBufferNumElements<StoreData>()};
Result Get3(Out<u32> out_mii_count, SourceFlag source_flag,
OutArray<StoreData, BufferAttr_HipcMapAlias> store_data_buffer) {
const auto result = manager->Get(metadata, store_data_buffer, *out_mii_count, source_flag);
u32 mii_count{};
std::vector<StoreData> store_data(output_size);
const auto result = manager->Get(metadata, store_data, mii_count, source_flag);
LOG_INFO(Service_Mii, "called with source_flag={}, mii_count={}", source_flag,
*out_mii_count);
if (mii_count != 0) {
ctx.WriteBuffer(store_data);
}
LOG_INFO(Service_Mii, "called with source_flag={}, out_size={}, mii_count={}", source_flag,
output_size, mii_count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push(mii_count);
R_RETURN(result);
}
void UpdateLatest1(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto store_data{rp.PopRaw<StoreData>()};
const auto source_flag{rp.PopRaw<SourceFlag>()};
Result UpdateLatest1(Out<StoreData> out_store_data, StoreData& store_data,
SourceFlag source_flag) {
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
R_UNLESS(is_system, ResultPermissionDenied);
Result result = ResultSuccess;
if (!is_system) {
result = ResultPermissionDenied;
}
StoreData new_store_data{};
if (result.IsSuccess()) {
result = manager->UpdateLatest(metadata, new_store_data, store_data, source_flag);
}
if (result.IsFailure()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
return;
}
IPC::ResponseBuilder rb{ctx, 2 + sizeof(StoreData) / sizeof(u32)};
rb.Push(ResultSuccess);
rb.PushRaw<StoreData>(new_store_data);
R_RETURN(manager->UpdateLatest(metadata, *out_store_data, store_data, source_flag));
}
void FindIndex(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto create_id{rp.PopRaw<Common::UUID>()};
const auto is_special{rp.PopRaw<bool>()};
Result FindIndex(Out<s32> out_index, Common::UUID create_id, bool is_special) {
LOG_INFO(Service_Mii, "called with create_id={}, is_special={}",
create_id.FormattedString(), is_special);
const s32 index = manager->FindIndex(create_id, is_special);
*out_index = manager->FindIndex(create_id, is_special);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(index);
R_SUCCEED();
}
void Move(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto create_id{rp.PopRaw<Common::UUID>()};
const auto new_index{rp.PopRaw<s32>()};
Result Move(Common::UUID create_id, s32 new_index) {
LOG_INFO(Service_Mii, "called with create_id={}, new_index={}", create_id.FormattedString(),
new_index);
R_UNLESS(is_system, ResultPermissionDenied);
Result result = ResultSuccess;
if (!is_system) {
result = ResultPermissionDenied;
}
const u32 count = manager->GetCount(metadata, SourceFlag::Database);
if (result.IsSuccess()) {
const u32 count = manager->GetCount(metadata, SourceFlag::Database);
if (new_index < 0 || new_index >= static_cast<s32>(count)) {
result = ResultInvalidArgument;
}
}
R_UNLESS(new_index >= 0 && new_index < static_cast<s32>(count), ResultInvalidArgument);
if (result.IsSuccess()) {
result = manager->Move(metadata, new_index, create_id);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(manager->Move(metadata, new_index, create_id));
}
void AddOrReplace(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto store_data{rp.PopRaw<StoreData>()};
Result AddOrReplace(StoreData& store_data) {
LOG_INFO(Service_Mii, "called");
R_UNLESS(is_system, ResultPermissionDenied);
Result result = ResultSuccess;
const auto result = manager->AddOrReplace(metadata, store_data);
if (!is_system) {
result = ResultPermissionDenied;
}
if (result.IsSuccess()) {
result = manager->AddOrReplace(metadata, store_data);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(result);
}
void Delete(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto create_id{rp.PopRaw<Common::UUID>()};
Result Delete(Common::UUID create_id) {
LOG_INFO(Service_Mii, "called, create_id={}", create_id.FormattedString());
R_UNLESS(is_system, ResultPermissionDenied);
Result result = ResultSuccess;
if (!is_system) {
result = ResultPermissionDenied;
}
if (result.IsSuccess()) {
result = manager->Delete(metadata, create_id);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(manager->Delete(metadata, create_id));
}
void DestroyFile(HLERequestContext& ctx) {
// This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled");
const bool is_db_test_mode_enabled = false;
Result DestroyFile() {
bool is_db_test_mode_enabled{};
m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
Result result = ResultSuccess;
if (!is_db_test_mode_enabled) {
result = ResultTestModeOnly;
}
if (result.IsSuccess()) {
result = manager->DestroyFile(metadata);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(manager->DestroyFile(metadata));
}
void DeleteFile(HLERequestContext& ctx) {
// This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled");
const bool is_db_test_mode_enabled = false;
Result DeleteFile() {
bool is_db_test_mode_enabled{};
m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
Result result = ResultSuccess;
if (!is_db_test_mode_enabled) {
result = ResultTestModeOnly;
}
if (result.IsSuccess()) {
result = manager->DeleteFile();
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(manager->DeleteFile());
}
void Format(HLERequestContext& ctx) {
// This calls nn::settings::fwdbg::GetSettingsItemValue("is_db_test_mode_enabled");
const bool is_db_test_mode_enabled = false;
Result Format() {
bool is_db_test_mode_enabled{};
m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
Result result = ResultSuccess;
if (!is_db_test_mode_enabled) {
result = ResultTestModeOnly;
}
if (result.IsSuccess()) {
result = manager->Format(metadata);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(manager->Format(metadata));
}
void IsBrokenDatabaseWithClearFlag(HLERequestContext& ctx) {
Result IsBrokenDatabaseWithClearFlag(Out<bool> out_is_broken_with_clear_flag) {
LOG_DEBUG(Service_Mii, "called");
R_UNLESS(is_system, ResultPermissionDenied);
*out_is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
R_SUCCEED();
}
Result GetIndex(Out<s32> out_index, CharInfo& char_info) {
LOG_DEBUG(Service_Mii, "called");
bool is_broken_with_clear_flag = false;
Result result = ResultSuccess;
if (!is_system) {
result = ResultPermissionDenied;
}
if (result.IsSuccess()) {
is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push<u8>(is_broken_with_clear_flag);
R_RETURN(manager->GetIndex(metadata, char_info, *out_index));
}
void GetIndex(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto info{rp.PopRaw<CharInfo>()};
LOG_DEBUG(Service_Mii, "called");
s32 index{};
const auto result = manager->GetIndex(metadata, info, index);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push(index);
}
void SetInterfaceVersion(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto interface_version{rp.PopRaw<u32>()};
Result SetInterfaceVersion(u32 interface_version) {
LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
manager->SetInterfaceVersion(metadata, interface_version);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
R_SUCCEED();
}
void Convert(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
Result Convert(Out<CharInfo> out_char_info, Ver3StoreData& mii_v3) {
LOG_INFO(Service_Mii, "called");
CharInfo char_info{};
const auto result = manager->ConvertV3ToCharInfo(char_info, mii_v3);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(result);
rb.PushRaw<CharInfo>(char_info);
R_RETURN(manager->ConvertV3ToCharInfo(*out_char_info, mii_v3));
}
void ConvertCoreDataToCharInfo(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto core_data{rp.PopRaw<CoreData>()};
Result ConvertCoreDataToCharInfo(Out<CharInfo> out_char_info, CoreData& core_data) {
LOG_INFO(Service_Mii, "called");
CharInfo char_info{};
const auto result = manager->ConvertCoreDataToCharInfo(char_info, core_data);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(result);
rb.PushRaw<CharInfo>(char_info);
R_RETURN(manager->ConvertCoreDataToCharInfo(*out_char_info, core_data));
}
void ConvertCharInfoToCoreData(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto char_info{rp.PopRaw<CharInfo>()};
Result ConvertCharInfoToCoreData(Out<CoreData> out_core_data, CharInfo& char_info) {
LOG_INFO(Service_Mii, "called");
CoreData core_data{};
const auto result = manager->ConvertCharInfoToCoreData(core_data, char_info);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CoreData) / sizeof(u32)};
rb.Push(result);
rb.PushRaw<CoreData>(core_data);
R_RETURN(manager->ConvertCharInfoToCoreData(*out_core_data, char_info));
}
void Append(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto char_info{rp.PopRaw<CharInfo>()};
Result Append(CharInfo& char_info) {
LOG_INFO(Service_Mii, "called");
const auto result = manager->Append(metadata, char_info);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
R_RETURN(manager->Append(metadata, char_info));
}
std::shared_ptr<MiiManager> manager = nullptr;
DatabaseSessionMetadata metadata{};
bool is_system{};
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
};
MiiDBModule::MiiDBModule(Core::System& system_, const char* name_,
std::shared_ptr<MiiManager> mii_manager, bool is_system_)
IStaticService::IStaticService(Core::System& system_, const char* name_,
std::shared_ptr<MiiManager> mii_manager, bool is_system_)
: ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
{0, D<&IStaticService::GetDatabaseService>, "GetDatabaseService"},
};
// clang-format on
RegisterHandlers(functions);
if (manager == nullptr) {
manager = std::make_shared<MiiManager>();
}
}
MiiDBModule::~MiiDBModule() = default;
void MiiDBModule::GetDatabaseService(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IDatabaseService>(system, manager, is_system);
IStaticService::~IStaticService() = default;
Result IStaticService::GetDatabaseService(
Out<SharedPointer<IDatabaseService>> out_database_service) {
LOG_DEBUG(Service_Mii, "called");
*out_database_service = std::make_shared<IDatabaseService>(system, manager, is_system);
R_SUCCEED();
}
std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() {
std::shared_ptr<MiiManager> IStaticService::GetMiiManager() {
return manager;
}
class MiiImg final : public ServiceFramework<MiiImg> {
class IImageDatabaseService final : public ServiceFramework<IImageDatabaseService> {
public:
explicit MiiImg(Core::System& system_) : ServiceFramework{system_, "miiimg"} {
explicit IImageDatabaseService(Core::System& system_) : ServiceFramework{system_, "miiimg"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &MiiImg::Initialize, "Initialize"},
{0, D<&IImageDatabaseService::Initialize>, "Initialize"},
{10, nullptr, "Reload"},
{11, &MiiImg::GetCount, "GetCount"},
{11, D<&IImageDatabaseService::GetCount>, "GetCount"},
{12, nullptr, "IsEmpty"},
{13, nullptr, "IsFull"},
{14, nullptr, "GetAttribute"},
@@ -585,31 +341,30 @@ public:
}
private:
void Initialize(HLERequestContext& ctx) {
Result Initialize() {
LOG_INFO(Service_Mii, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
R_SUCCEED();
}
void GetCount(HLERequestContext& ctx) {
Result GetCount(Out<u32> out_count) {
LOG_DEBUG(Service_Mii, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
*out_count = 0;
R_SUCCEED();
}
};
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
std::shared_ptr<MiiManager> manager = nullptr;
std::shared_ptr<MiiManager> manager = std::make_shared<MiiManager>();
server_manager->RegisterNamedService(
"mii:e", std::make_shared<MiiDBModule>(system, "mii:e", manager, true));
"mii:e", std::make_shared<IStaticService>(system, "mii:e", manager, true));
server_manager->RegisterNamedService(
"mii:u", std::make_shared<MiiDBModule>(system, "mii:u", manager, false));
server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
"mii:u", std::make_shared<IStaticService>(system, "mii:u", manager, false));
server_manager->RegisterNamedService("miiimg", std::make_shared<IImageDatabaseService>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@@ -3,7 +3,7 @@
#pragma once
#include "core/hle/service/service.h"
#include "core/hle/service/cmif_types.h"
namespace Core {
class System;
@@ -11,19 +11,20 @@ class System;
namespace Service::Mii {
class MiiManager;
class IDatabaseService;
class MiiDBModule final : public ServiceFramework<MiiDBModule> {
class IStaticService final : public ServiceFramework<IStaticService> {
public:
explicit MiiDBModule(Core::System& system_, const char* name_,
std::shared_ptr<MiiManager> mii_manager, bool is_system_);
~MiiDBModule() override;
explicit IStaticService(Core::System& system_, const char* name_,
std::shared_ptr<MiiManager> mii_manager, bool is_system_);
~IStaticService() override;
std::shared_ptr<MiiManager> GetMiiManager();
private:
void GetDatabaseService(HLERequestContext& ctx);
Result GetDatabaseService(Out<SharedPointer<IDatabaseService>> out_database_service);
std::shared_ptr<MiiManager> manager = nullptr;
std::shared_ptr<MiiManager> manager{nullptr};
bool is_system{};
};

View File

@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/hle/service/set/setting_formats/system_settings.h"
namespace Service::Set {
@@ -52,6 +53,17 @@ SystemSettings DefaultSystemSettings() {
settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0;
settings.vibration_master_volume = 1.0f;
const auto language_code =
available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
const auto key_code =
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
[=](const auto& element) { return element.first == language_code; });
settings.keyboard_layout = KeyboardLayout::EnglishUs;
if (key_code != language_to_layout.end()) {
settings.keyboard_layout = key_code->second;
}
return settings;
}

View File

@@ -213,10 +213,9 @@ struct SystemSettings {
// nn::settings::system::AudioVolume
std::array<u8, 0x8> audio_volume_type0;
std::array<u8, 0x8> audio_volume_type1;
// nn::settings::system::AudioOutputMode
s32 audio_output_mode_type0;
s32 audio_output_mode_type1;
s32 audio_output_mode_type2;
AudioOutputMode audio_output_mode_hdmi;
AudioOutputMode audio_output_mode_speaker;
AudioOutputMode audio_output_mode_headphone;
bool force_mute_on_headphone_removed;
INSERT_PADDING_BYTES(0x3);
s32 headphone_volume_warning_count;
@@ -224,9 +223,8 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x3);
// nn::settings::system::AudioVolume
std::array<u8, 0x8> audio_volume_type2;
// nn::settings::system::AudioOutputMode
s32 audio_output_mode_type3;
s32 audio_output_mode_type4;
AudioOutputMode audio_output_mode_type3;
AudioOutputMode audio_output_mode_type4;
bool hearing_protection_safeguard_flag;
INSERT_PADDING_BYTES(0x3);
INSERT_PADDING_BYTES(0x4); // Reserved

View File

@@ -23,9 +23,12 @@ enum class AudioOutputMode : u32 {
/// This is nn::settings::system::AudioOutputModeTarget
enum class AudioOutputModeTarget : u32 {
None,
Hdmi,
Speaker,
Headphone,
Type3,
Type4,
};
/// This is nn::settings::system::AudioVolumeTarget
@@ -367,6 +370,12 @@ struct AccountNotificationSettings {
static_assert(sizeof(AccountNotificationSettings) == 0x18,
"AccountNotificationSettings is an invalid size");
/// This is nn::settings::factory::BatteryLot
struct BatteryLot {
std::array<char, 0x18> lot_number;
};
static_assert(sizeof(BatteryLot) == 0x18, "BatteryLot is an invalid size");
/// This is nn::settings::system::EulaVersion
struct EulaVersion {
u32 version;
@@ -436,6 +445,12 @@ struct NotificationSettings {
};
static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size");
/// This is nn::settings::factory::SerialNumber
struct SerialNumber {
std::array<char, 0x18> serial_number;
};
static_assert(sizeof(SerialNumber) == 0x18, "SerialNumber is an invalid size");
/// This is nn::settings::system::SleepSettings
struct SleepSettings {
SleepFlag flags;

View File

@@ -25,7 +25,7 @@
namespace Service::Set {
namespace {
constexpr u32 SETTINGS_VERSION{1u};
constexpr u32 SETTINGS_VERSION{2u};
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
struct SettingsHeader {
u64 magic;
@@ -131,10 +131,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
{41, nullptr, "GetEdid"},
{42, nullptr, "SetEdid"},
{43, nullptr, "GetAudioOutputMode"},
{44, nullptr, "SetAudioOutputMode"},
{45, &ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved, "IsForceMuteOnHeadphoneRemoved"},
{46, &ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved, "SetForceMuteOnHeadphoneRemoved"},
{43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"},
{44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"},
{45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"},
{46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"},
{47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
{48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
{49, nullptr, "GetDataDeletionSettings"},
@@ -155,8 +155,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"},
{66, nullptr, "SetUsb30EnableFlag"},
{67, nullptr, "GetBatteryLot"},
{68, nullptr, "GetSerialNumber"},
{67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"},
{68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"},
{69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
{70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
{71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
@@ -184,11 +184,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
{94, nullptr, "GetFatalDirtyFlags"},
{95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
{96, nullptr, "SetAutoUpdateEnableFlag"},
{96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"},
{97, nullptr, "GetNxControllerSettings"},
{98, nullptr, "SetNxControllerSettings"},
{99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
{100, nullptr, "SetBatteryPercentageFlag"},
{100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"},
{101, nullptr, "GetExternalRtcResetFlag"},
{102, nullptr, "SetExternalRtcResetFlag"},
{103, nullptr, "GetUsbFullKeyEnableFlag"},
@@ -208,12 +208,12 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
{119, nullptr, "NeedsToUpdateHeadphoneVolume"},
{120, nullptr, "GetPushNotificationActivityModeOnSleep"},
{121, nullptr, "SetPushNotificationActivityModeOnSleep"},
{120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"},
{121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"},
{122, nullptr, "GetServiceDiscoveryControlSettings"},
{123, nullptr, "SetServiceDiscoveryControlSettings"},
{124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
{125, nullptr, "SetErrorReportSharePermission"},
{125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"},
{126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
{127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
@@ -225,7 +225,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
{136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
{137, nullptr, "SetKeyboardLayout"},
{137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"},
{138, nullptr, "GetWebInspectorFlag"},
{139, nullptr, "GetAllowedSslHosts"},
{140, nullptr, "GetHostFsMountPoint"},
@@ -291,8 +291,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{200, nullptr, "SetButtonConfigRegisteredSettings"},
{201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
{202, nullptr, "SetFieldTestingFlag"},
{203, nullptr, "GetPanelCrcMode"},
{204, nullptr, "SetPanelCrcMode"},
{203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"},
{204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"},
{205, nullptr, "GetNxControllerSettingsEx"},
{206, nullptr, "SetNxControllerSettingsEx"},
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
@@ -349,7 +349,7 @@ bool ISystemSettingsServer::LoadSettingsFile(std::filesystem::path& path, auto&&
}
SettingsHeader hdr{};
file.read(reinterpret_cast<char*>(&hdr), sizeof(hdr));
return hdr.magic == SETTINGS_MAGIC && hdr.version == SETTINGS_VERSION;
return hdr.magic == SETTINGS_MAGIC && hdr.version >= SETTINGS_VERSION;
};
if (!exists || !file_size_ok) {
@@ -390,7 +390,7 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
}
auto settings_base = path / "settings";
auto settings_tmp_file = settings_base;
std::filesystem::path settings_tmp_file = settings_base;
settings_tmp_file = settings_tmp_file.replace_extension("tmp");
std::ofstream file(settings_tmp_file, std::ios::binary | std::ios::out);
if (!file.is_open()) {
@@ -722,6 +722,9 @@ static Settings GetSettings() {
ret["hid_debug"]["disabled_features_per_id"] = std::vector<u8>(0xa8);
ret["hid_debug"]["touch_firmware_auto_update_disabled"] = ToBytes(bool{false});
// Mii
ret["mii"]["is_db_test_mode_enabled"] = ToBytes(bool{false});
// Settings
ret["settings_debug"]["is_debug_mode_enabled"] = ToBytes(bool{false});
@@ -814,7 +817,34 @@ void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto target{rp.PopEnum<AudioOutputModeTarget>()};
AudioOutputMode output_mode{};
const auto result = GetAudioOutputMode(output_mode, target);
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.PushEnum(output_mode);
}
void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto target{rp.PopEnum<AudioOutputModeTarget>()};
const auto output_mode{rp.PopEnum<AudioOutputMode>()};
const auto result = SetAudioOutputMode(target, output_mode);
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
}
void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
m_system_settings.force_mute_on_headphone_removed);
@@ -823,7 +853,7 @@ void ISystemSettingsServer::IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx
rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
}
void ISystemSettingsServer::SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx) {
void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
SetSaveNeeded();
@@ -966,6 +996,26 @@ void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) {
BatteryLot battery_lot = {"YUZUEMULATOR123456789"};
LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 8};
rb.Push(ResultSuccess);
rb.PushRaw(battery_lot);
}
void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) {
SerialNumber console_serial = {"YUZ10012345678"};
LOG_INFO(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 8};
rb.Push(ResultSuccess);
rb.PushRaw(console_serial);
}
void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
@@ -1129,6 +1179,17 @@ void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.auto_update_enable_flag);
}
void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.auto_update_enable_flag = rp.Pop<bool>();
SetSaveNeeded();
LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
m_system_settings.battery_percentage_flag);
@@ -1138,6 +1199,18 @@ void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.battery_percentage_flag);
}
void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.battery_percentage_flag = rp.Pop<bool>();
SetSaveNeeded();
LOG_INFO(Service_SET, "called, battery_percentage_flag={}",
m_system_settings.battery_percentage_flag);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called.");
@@ -1161,6 +1234,27 @@ void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestConte
rb.Push(offset);
}
void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
m_system_settings.push_notification_activity_mode_on_sleep);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(m_system_settings.push_notification_activity_mode_on_sleep);
}
void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>();
SetSaveNeeded();
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
m_system_settings.push_notification_activity_mode_on_sleep);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
m_system_settings.error_report_share_permission);
@@ -1170,6 +1264,18 @@ void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx
rb.PushEnum(m_system_settings.error_report_share_permission);
}
void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>();
SetSaveNeeded();
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
m_system_settings.error_report_share_permission);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
@@ -1190,22 +1296,22 @@ void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
}
void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
const auto language_code =
available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())];
const auto key_code =
std::find_if(language_to_layout.cbegin(), language_to_layout.cend(),
[=](const auto& element) { return element.first == language_code; });
KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs;
if (key_code != language_to_layout.end()) {
selected_keyboard_layout = key_code->second;
}
LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout);
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(selected_keyboard_layout));
rb.Push(static_cast<u32>(m_system_settings.keyboard_layout));
}
void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>();
SetSaveNeeded();
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
@@ -1297,6 +1403,25 @@ void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
rb.Push(m_system_settings.field_testing_flag);
}
void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(m_system_settings.panel_crc_mode);
}
void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
m_system_settings.panel_crc_mode = rp.PopRaw<s32>();
SetSaveNeeded();
LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ISystemSettingsServer::SetupSettings() {
auto system_dir =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
@@ -1387,6 +1512,66 @@ Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
R_SUCCEED();
}
Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode,
AudioOutputModeTarget target) const {
switch (target) {
case AudioOutputModeTarget::Hdmi:
out_output_mode = m_system_settings.audio_output_mode_hdmi;
break;
case AudioOutputModeTarget::Speaker:
out_output_mode = m_system_settings.audio_output_mode_speaker;
break;
case AudioOutputModeTarget::Headphone:
out_output_mode = m_system_settings.audio_output_mode_headphone;
break;
case AudioOutputModeTarget::Type3:
out_output_mode = m_system_settings.audio_output_mode_type3;
break;
case AudioOutputModeTarget::Type4:
out_output_mode = m_system_settings.audio_output_mode_type4;
break;
default:
LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
}
R_SUCCEED();
}
Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
AudioOutputMode output_mode) {
switch (target) {
case AudioOutputModeTarget::Hdmi:
m_system_settings.audio_output_mode_hdmi = output_mode;
break;
case AudioOutputModeTarget::Speaker:
m_system_settings.audio_output_mode_speaker = output_mode;
break;
case AudioOutputModeTarget::Headphone:
m_system_settings.audio_output_mode_headphone = output_mode;
break;
case AudioOutputModeTarget::Type3:
m_system_settings.audio_output_mode_type3 = output_mode;
break;
case AudioOutputModeTarget::Type4:
m_system_settings.audio_output_mode_type4 = output_mode;
break;
default:
LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
}
SetSaveNeeded();
R_SUCCEED();
}
Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const {
is_auto_mute = m_system_settings.force_mute_on_headphone_removed;
R_SUCCEED();
}
Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) {
m_system_settings.force_mute_on_headphone_removed = is_auto_mute;
SetSaveNeeded();
R_SUCCEED();
}
Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
out_id = m_private_settings.external_clock_source_id;
R_SUCCEED();

View File

@@ -50,6 +50,10 @@ public:
Result GetVibrationMasterVolume(f32& out_volume) const;
Result SetVibrationMasterVolume(f32 volume);
Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const;
Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode);
Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const;
Result SetSpeakerAutoMuteFlag(bool auto_mute);
Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
Result SetExternalSteadyClockSourceId(const Common::UUID& id);
Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
@@ -97,8 +101,10 @@ private:
void GetSettingsItemValue(HLERequestContext& ctx);
void GetTvSettings(HLERequestContext& ctx);
void SetTvSettings(HLERequestContext& ctx);
void IsForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
void SetForceMuteOnHeadphoneRemoved(HLERequestContext& ctx);
void GetAudioOutputMode(HLERequestContext& ctx);
void SetAudioOutputMode(HLERequestContext& ctx);
void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
void GetDebugModeFlag(HLERequestContext& ctx);
void GetQuestFlag(HLERequestContext& ctx);
void SetQuestFlag(HLERequestContext& ctx);
@@ -111,6 +117,8 @@ private:
void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void GetPrimaryAlbumStorage(HLERequestContext& ctx);
void SetPrimaryAlbumStorage(HLERequestContext& ctx);
void GetBatteryLot(HLERequestContext& ctx);
void GetSerialNumber(HLERequestContext& ctx);
void GetNfcEnableFlag(HLERequestContext& ctx);
void SetNfcEnableFlag(HLERequestContext& ctx);
void GetSleepSettings(HLERequestContext& ctx);
@@ -126,13 +134,19 @@ private:
void SetBluetoothEnableFlag(HLERequestContext& ctx);
void GetMiiAuthorId(HLERequestContext& ctx);
void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
void GetBatteryPercentageFlag(HLERequestContext& ctx);
void SetBatteryPercentageFlag(HLERequestContext& ctx);
void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
void GetErrorReportSharePermission(HLERequestContext& ctx);
void SetErrorReportSharePermission(HLERequestContext& ctx);
void GetAppletLaunchFlags(HLERequestContext& ctx);
void SetAppletLaunchFlags(HLERequestContext& ctx);
void GetKeyboardLayout(HLERequestContext& ctx);
void SetKeyboardLayout(HLERequestContext& ctx);
void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
@@ -141,6 +155,8 @@ private:
void GetHomeMenuScheme(HLERequestContext& ctx);
void GetHomeMenuSchemeModel(HLERequestContext& ctx);
void GetFieldTestingFlag(HLERequestContext& ctx);
void GetPanelCrcMode(HLERequestContext& ctx);
void SetPanelCrcMode(HLERequestContext& ctx);
bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
bool StoreSettingsFile(std::filesystem::path& path, auto& settings);

View File

@@ -781,8 +781,7 @@ struct Memory::Impl {
},
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); });
if (ptr) {
const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr);
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
return Common::AtomicCompareAndSwap(reinterpret_cast<T*>(ptr), data, expected);
}
return true;
}
@@ -796,8 +795,7 @@ struct Memory::Impl {
},
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); });
if (ptr) {
const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr);
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
return Common::AtomicCompareAndSwap(reinterpret_cast<u64*>(ptr), data, expected);
}
return true;
}

View File

@@ -298,6 +298,16 @@ void Config::ReadDebuggingValues() {
EndGroup();
}
#ifdef __unix__
void Config::ReadLinuxValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
ReadCategory(Settings::Category::Linux);
EndGroup();
}
#endif
void Config::ReadServiceValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));
@@ -404,6 +414,9 @@ void Config::ReadValues() {
ReadControlValues();
ReadCoreValues();
ReadCpuValues();
#ifdef __unix__
ReadLinuxValues();
#endif
ReadRendererValues();
ReadAudioValues();
ReadSystemValues();
@@ -504,6 +517,9 @@ void Config::SaveValues() {
SaveControlValues();
SaveCoreValues();
SaveCpuValues();
#ifdef __unix__
SaveLinuxValues();
#endif
SaveRendererValues();
SaveAudioValues();
SaveSystemValues();
@@ -578,6 +594,16 @@ void Config::SaveDebuggingValues() {
EndGroup();
}
#ifdef __unix__
void Config::SaveLinuxValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Linux));
WriteCategory(Settings::Category::Linux);
EndGroup();
}
#endif
void Config::SaveNetworkValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Services));

View File

@@ -76,6 +76,9 @@ protected:
void ReadCoreValues();
void ReadDataStorageValues();
void ReadDebuggingValues();
#ifdef __unix__
void ReadLinuxValues();
#endif
void ReadServiceValues();
void ReadDisabledAddOnValues();
void ReadMiscellaneousValues();
@@ -107,6 +110,9 @@ protected:
void SaveCoreValues();
void SaveDataStorageValues();
void SaveDebuggingValues();
#ifdef __unix__
void SaveLinuxValues();
#endif
void SaveNetworkValues();
void SaveDisabledAddOnValues();
void SaveMiscellaneousValues();

View File

@@ -184,7 +184,7 @@ void ResourceManager::InitializeHidCommonSampler() {
keyboard->SetAppletResource(applet_resource, &shared_mutex);
const auto settings =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys");
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, settings);
six_axis->SetAppletResource(applet_resource, &shared_mutex);

View File

@@ -137,7 +137,7 @@ void NpadAbstractPropertiesHandler::UpdateAllDeviceProperties() {
const auto npad_index = NpadIdTypeToIndex(npad_id_type);
for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
auto* data = applet_resource_holder->applet_resource->GetAruidData(aruid_index);
if (!data->flag.is_assigned) {
if (data == nullptr || !data->flag.is_assigned) {
continue;
}
auto& npad_entry = data->shared_memory_format->npad.npad_entry[npad_index];

View File

@@ -8,7 +8,8 @@
namespace Service::HID {
HidFirmwareSettings::HidFirmwareSettings(Core::System& system) {
m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys");
m_set_sys =
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
LoadSettings(true);
}

View File

@@ -96,6 +96,9 @@ add_executable(yuzu
configuration/configure_input_profile_dialog.cpp
configuration/configure_input_profile_dialog.h
configuration/configure_input_profile_dialog.ui
configuration/configure_linux_tab.cpp
configuration/configure_linux_tab.h
configuration/configure_linux_tab.ui
configuration/configure_mouse_panning.cpp
configuration/configure_mouse_panning.h
configuration/configure_mouse_panning.ui

View File

@@ -24,6 +24,8 @@ class Builder;
}
class ConfigureAudio : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureAudio(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,

View File

@@ -24,6 +24,8 @@ class Builder;
}
class ConfigureCpu : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureCpu(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,

View File

@@ -25,6 +25,8 @@ class Builder;
}
class ConfigureGeneral : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureGeneral(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,

View File

@@ -224,6 +224,11 @@ void ConfigureGraphics::PopulateVSyncModeSelection(bool use_setting) {
}
void ConfigureGraphics::UpdateVsyncSetting() const {
const Settings::RendererBackend backend{GetCurrentGraphicsBackend()};
if (backend == Settings::RendererBackend::Null) {
return;
}
const auto mode = vsync_mode_combobox_enum_map[vsync_mode_combobox->currentIndex()];
const auto vsync_mode = PresentModeToSetting(mode);
Settings::values.vsync_mode.SetValue(vsync_mode);

View File

@@ -43,6 +43,8 @@ class Builder;
}
class ConfigureGraphics : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureGraphics(
const Core::System& system_, std::vector<VkDeviceInfo::Record>& records,

View File

@@ -21,6 +21,8 @@ class Builder;
}
class ConfigureGraphicsAdvanced : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureGraphicsAdvanced(
const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,

View File

@@ -0,0 +1,75 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_linux_tab.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_linux_tab.h"
#include "yuzu/configuration/shared_widget.h"
ConfigureLinuxTab::ConfigureLinuxTab(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
const ConfigurationShared::Builder& builder, QWidget* parent)
: Tab(group_, parent), ui(std::make_unique<Ui::ConfigureLinuxTab>()), system{system_} {
ui->setupUi(this);
Setup(builder);
SetConfiguration();
}
ConfigureLinuxTab::~ConfigureLinuxTab() = default;
void ConfigureLinuxTab::SetConfiguration() {}
void ConfigureLinuxTab::Setup(const ConfigurationShared::Builder& builder) {
QLayout& linux_layout = *ui->linux_widget->layout();
std::map<u32, QWidget*> linux_hold{};
std::vector<Settings::BasicSetting*> settings;
const auto push = [&](Settings::Category category) {
for (const auto setting : Settings::values.linkage.by_category[category]) {
settings.push_back(setting);
}
};
push(Settings::Category::Linux);
for (auto* setting : settings) {
auto* widget = builder.BuildWidget(setting, apply_funcs);
if (widget == nullptr) {
continue;
}
if (!widget->Valid()) {
widget->deleteLater();
continue;
}
linux_hold.insert({setting->Id(), widget});
}
for (const auto& [id, widget] : linux_hold) {
linux_layout.addWidget(widget);
}
}
void ConfigureLinuxTab::ApplyConfiguration() {
const bool is_powered_on = system.IsPoweredOn();
for (const auto& apply_func : apply_funcs) {
apply_func(is_powered_on);
}
}
void ConfigureLinuxTab::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QWidget::changeEvent(event);
}
void ConfigureLinuxTab::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QWidget>
namespace Core {
class System;
}
namespace Ui {
class ConfigureLinuxTab;
}
namespace ConfigurationShared {
class Builder;
}
class ConfigureLinuxTab : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureLinuxTab(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
const ConfigurationShared::Builder& builder,
QWidget* parent = nullptr);
~ConfigureLinuxTab() override;
void ApplyConfiguration() override;
void SetConfiguration() override;
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
void Setup(const ConfigurationShared::Builder& builder);
std::unique_ptr<Ui::ConfigureLinuxTab> ui;
const Core::System& system;
std::vector<std::function<void(bool)>> apply_funcs{};
};

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureLinuxTab</class>
<widget class="QWidget" name="ConfigureLinuxTab">
<property name="accessibleName">
<string>Linux</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox" name="LinuxGroupBox">
<property name="title">
<string>Linux</string>
</property>
<layout class="QVBoxLayout" name="LinuxVerticalLayout_1">
<item>
<widget class="QWidget" name="linux_widget" native="true">
<layout class="QVBoxLayout" name="LinuxVerticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -26,6 +26,7 @@ class ConfigureMotionTouch;
/// A dialog for touchpad calibration configuration.
class CalibrationConfigurationDialog : public QDialog {
Q_OBJECT
public:
explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port);
~CalibrationConfigurationDialog() override;

View File

@@ -16,6 +16,7 @@ class ConfigureMousePanning;
class ConfigureMousePanning : public QDialog {
Q_OBJECT
public:
explicit ConfigureMousePanning(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_,
float right_stick_deadzone, float right_stick_range);

View File

@@ -33,6 +33,7 @@
#include "yuzu/configuration/configure_graphics.h"
#include "yuzu/configuration/configure_graphics_advanced.h"
#include "yuzu/configuration/configure_input_per_game.h"
#include "yuzu/configuration/configure_linux_tab.h"
#include "yuzu/configuration/configure_per_game.h"
#include "yuzu/configuration/configure_per_game_addons.h"
#include "yuzu/configuration/configure_system.h"
@@ -60,6 +61,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
[](Settings::AspectRatio, Settings::ResolutionSetup) {}, tab_group, *builder, this);
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
linux_tab = std::make_unique<ConfigureLinuxTab>(system_, tab_group, *builder, this);
system_tab = std::make_unique<ConfigureSystem>(system_, tab_group, *builder, this);
ui->setupUi(this);
@@ -71,6 +73,10 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics"));
ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles"));
// Only show Linux tab on Unix
#ifdef __unix__
ui->tabWidget->addTab(linux_tab.get(), tr("Linux"));
#endif
setFocusPolicy(Qt::ClickFocus);
setWindowTitle(tr("Properties"));

View File

@@ -32,6 +32,7 @@ class ConfigureCpu;
class ConfigureGraphics;
class ConfigureGraphicsAdvanced;
class ConfigureInputPerGame;
class ConfigureLinuxTab;
class ConfigureSystem;
class QGraphicsScene;
@@ -85,5 +86,6 @@ private:
std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
std::unique_ptr<ConfigureGraphics> graphics_tab;
std::unique_ptr<ConfigureInputPerGame> input_tab;
std::unique_ptr<ConfigureLinuxTab> linux_tab;
std::unique_ptr<ConfigureSystem> system_tab;
};

View File

@@ -27,6 +27,8 @@ class Builder;
}
class ConfigureSystem : public ConfigurationShared::Tab {
Q_OBJECT
public:
explicit ConfigureSystem(Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,