Compare commits

..

35 Commits

Author SHA1 Message Date
yuzubot
252e8acde5 Android 217 2024-01-28 20:07:43 +00:00
yuzubot
c867143204 Merge yuzu-emu#12830 2024-01-28 20:07:42 +00:00
yuzubot
d0f90ff4ed Merge yuzu-emu#12814 2024-01-28 20:07:42 +00:00
yuzubot
d62f40109f Merge yuzu-emu#12760 2024-01-28 20:07:42 +00:00
yuzubot
508c950c87 Merge yuzu-emu#12749 2024-01-28 20:07:42 +00: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
Kelebek1
19a2f12692 Use the input process handle to get the correct application's memory 2024-01-28 18:51:43 +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
103 changed files with 2146 additions and 2294 deletions

View File

@@ -1,8 +1,9 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`eb46f21c5`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12802](https://github.com/yuzu-emu/yuzu-android//pull/12802) | [`c5e88c654`](https://github.com/yuzu-emu/yuzu-android//pull/12802/files) | service: mii: Migrate service to new interface | [german77](https://github.com/german77/) | Yes |
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`c6b88b62d`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
| [12814](https://github.com/yuzu-emu/yuzu-android//pull/12814) | [`da410506a`](https://github.com/yuzu-emu/yuzu-android//pull/12814/files) | Move time services to new IPC and add debug printing | [Kelebek1](https://github.com/Kelebek1/) | Yes |
| [12830](https://github.com/yuzu-emu/yuzu-android//pull/12830) | [`6cc82fd43`](https://github.com/yuzu-emu/yuzu-android//pull/12830/files) | externals/dynarmic: Update to 6.6.1 | [merryhime](https://github.com/merryhime/) | Yes |
End of merge log. You can find the original README.md below the break.

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

@@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) {
return 0;
}
bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) {
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) {
return localsub(sp, timep, 0, tmp) == nullptr;
}
u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) {
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) {
return time1(out_time, tmp, localsub, sp, 0);
}

View File

@@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th
s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary);
bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep);
u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp);
bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep);
u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp);
} // namespace Tz

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

@@ -61,6 +61,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
@@ -209,7 +212,14 @@ void EmulationSession::InitializeSystem(bool reload) {
m_system.GetFileSystemController().CreateFactories(*m_vfs);
}
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
void EmulationSession::SetAppletId(int applet_id) {
m_applet_id = applet_id;
m_system.GetFrontendAppletHolder().SetCurrentAppletId(
static_cast<Service::AM::AppletId>(m_applet_id));
}
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
const std::size_t program_index) {
std::scoped_lock lock(m_mutex);
// Create the render window.
@@ -240,7 +250,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
// Load the ROM.
Service::AM::FrontendAppletParameters params{
.applet_id = Service::AM::AppletId::Application,
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
.program_index = static_cast<s32>(program_index),
};
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
if (m_load_result != Core::SystemResultStatus::Success) {
@@ -252,6 +263,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;
}
@@ -259,6 +276,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.
@@ -327,6 +349,9 @@ void EmulationSession::RunEmulation() {
}
}
}
// Reset current applet ID.
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
}
bool EmulationSession::IsHandheldOnly() {
@@ -406,6 +431,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 {
@@ -415,7 +446,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(); });
@@ -428,7 +460,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;
}
@@ -525,6 +557,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());
@@ -693,11 +756,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));
@@ -759,8 +822,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
jint jappletId) {
EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCurrentAppletId(
static_cast<Service::AM::AppletId>(jappletId));
EmulationSession::GetInstance().SetAppletId(jappletId);
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,

View File

@@ -45,7 +45,9 @@ public:
const Core::PerfStatsResults& PerfStats();
void ConfigureFilesystemProvider(const std::string& filepath);
void InitializeSystem(bool reload);
Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
void SetAppletId(int applet_id);
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 +62,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
@@ -77,6 +80,7 @@ private:
std::atomic<bool> m_is_paused = false;
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
int m_applet_id{1};
// GPU driver parameters
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
@@ -84,4 +88,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

@@ -210,8 +210,6 @@ add_library(audio_core STATIC
sink/sink_stream.h
)
create_target_directory_groups(audio_core)
if (MSVC)
target_compile_options(audio_core PRIVATE
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
@@ -267,3 +265,5 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
endif()
create_target_directory_groups(audio_core)

View File

@@ -89,11 +89,13 @@ u32 AudioRenderer::Receive(Direction dir) {
}
void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, bool reset) noexcept {
u64 applet_resource_user_id, Kernel::KProcess* process,
bool reset) noexcept {
command_buffers[session_id].buffer = buffer;
command_buffers[session_id].size = size;
command_buffers[session_id].time_limit = time_limit;
command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
command_buffers[session_id].process = process;
command_buffers[session_id].reset_buffer = reset;
}
@@ -173,7 +175,8 @@ void AudioRenderer::Main(std::stop_token stop_token) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if (command_buffer.remaining_command_count == 0) {
command_list_processor.Initialize(system, command_buffer.buffer,
command_list_processor.Initialize(system, *command_buffer.process,
command_buffer.buffer,
command_buffer.size, streams[index]);
}

View File

@@ -19,6 +19,10 @@ namespace Core {
class System;
} // namespace Core
namespace Kernel {
class KProcess;
}
namespace AudioCore {
namespace Sink {
class Sink;
@@ -69,7 +73,8 @@ public:
u32 Receive(Direction dir);
void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, bool reset) noexcept;
u64 applet_resource_user_id, Kernel::KProcess* process,
bool reset) noexcept;
u32 GetRemainCommandCount(s32 session_id) const noexcept;
void ClearRemainCommandCount(s32 session_id) noexcept;
u64 GetRenderingStartTick(s32 session_id) const noexcept;

View File

@@ -6,6 +6,10 @@
#include "audio_core/common/common.h"
#include "common/common_types.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::ADSP::AudioRenderer {
struct CommandBuffer {
@@ -14,6 +18,7 @@ struct CommandBuffer {
u64 size{};
u64 time_limit{};
u64 applet_resource_user_id{};
Kernel::KProcess* process{};
bool reset_buffer{};
// Set by the DSP
u32 remaining_command_count{};

View File

@@ -9,14 +9,15 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_process.h"
#include "core/memory.h"
namespace AudioCore::ADSP::AudioRenderer {
void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
Sink::SinkStream* stream_) {
void CommandListProcessor::Initialize(Core::System& system_, Kernel::KProcess& process,
CpuAddr buffer, u64 size, Sink::SinkStream* stream_) {
system = &system_;
memory = &system->ApplicationMemory();
memory = &process.GetMemory();
stream = stream_;
header = reinterpret_cast<Renderer::CommandListHeader*>(buffer);
commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));

View File

@@ -16,6 +16,10 @@ class Memory;
class System;
} // namespace Core
namespace Kernel {
class KProcess;
}
namespace AudioCore {
namespace Sink {
class SinkStream;
@@ -40,7 +44,8 @@ public:
* @param size - The size of the buffer.
* @param stream - The stream to be used for sending the samples.
*/
void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream);
void Initialize(Core::System& system, Kernel::KProcess& process, CpuAddr buffer, u64 size,
Sink::SinkStream* stream);
/**
* Set the maximum processing time for this command list.

View File

@@ -6,6 +6,7 @@
#include "audio_core/renderer/audio_renderer.h"
#include "audio_core/renderer/system_manager.h"
#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/errors.h"
@@ -17,7 +18,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
Result Renderer::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, const u32 process_handle,
const u64 applet_resource_user_id, const s32 session_id) {
Kernel::KProcess& process, const u64 applet_resource_user_id,
const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio,
@@ -28,7 +30,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
}
initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
applet_resource_user_id, session_id);
return ResultSuccess;

View File

@@ -14,7 +14,8 @@ class System;
namespace Kernel {
class KTransferMemory;
}
class KProcess;
} // namespace Kernel
namespace AudioCore {
struct AudioRendererParameterInternal;
@@ -44,7 +45,8 @@ public:
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id);
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
s32 session_id);
/**
* Finalize the renderer for shutdown.

View File

@@ -32,6 +32,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/memory.h"
@@ -101,7 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) {
u32 process_handle_, Kernel::KProcess& process_,
u64 applet_resource_user_id_, s32 session_id_) {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ResultInvalidRevision;
}
@@ -117,6 +119,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
behavior.SetUserLibRevision(params.revision);
process_handle = process_handle_;
process = &process_;
applet_resource_user_id = applet_resource_user_id_;
session_id = session_id_;
@@ -129,7 +132,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device;
execution_mode = params.execution_mode;
core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for.
// Allocate the memory normally instead and hope the game doesn't try to read anything back
@@ -613,7 +616,8 @@ void System::SendCommandToDsp() {
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
applet_resource_user_id, reset_command_buffers);
applet_resource_user_id, process,
reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;
if (remaining_command_count == 0) {

View File

@@ -29,6 +29,7 @@ class System;
namespace Kernel {
class KEvent;
class KProcess;
class KTransferMemory;
} // namespace Kernel
@@ -80,7 +81,8 @@ public:
*/
Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id);
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id,
s32 session_id);
/**
* Finalize the system.
@@ -275,6 +277,8 @@ private:
Common::Event terminate_event{};
/// Does what locks do
std::mutex lock{};
/// Process this audio render is operating within, used for memory reads/writes.
Kernel::KProcess* process{};
/// Handle for the process for this system, unused
u32 process_handle{};
/// Applet resource id for this system, unused

View File

@@ -245,8 +245,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
)
endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
@@ -258,3 +256,5 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(common PRIVATE precompiled_headers.h)
endif()
create_target_directory_groups(common)

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

@@ -979,8 +979,6 @@ else()
)
endif()
create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz)
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
if (MINGW)
@@ -1058,3 +1056,5 @@ endif()
if (YUZU_ENABLE_LTO)
set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
create_target_directory_groups(core)

View File

@@ -201,22 +201,22 @@ struct System::Impl {
system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock;
static_service_a->GetStandardUserSystemClock(user_clock);
static_service_a->GetStandardUserSystemClock(&user_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
static_service_a->GetStandardLocalSystemClock(local_clock);
static_service_a->GetStandardLocalSystemClock(&local_clock);
std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
static_service_s->GetStandardNetworkSystemClock(network_clock);
static_service_s->GetStandardNetworkSystemClock(&network_clock);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service;
static_service_a->GetTimeZoneService(timezone_service);
static_service_a->GetTimeZoneService(&timezone_service);
Service::PSC::Time::LocationName name{};
auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size()));
std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size()));
timezone_service->SetDeviceLocation(name);
timezone_service->SetDeviceLocationName(name);
u64 time_offset = 0;
if (Settings::values.custom_rtc_enabled) {
@@ -234,7 +234,7 @@ struct System::Impl {
local_clock->SetCurrentTime(new_time);
network_clock->GetSystemClockContext(context);
network_clock->GetSystemClockContext(&context);
settings_service->SetNetworkSystemClockContext(context);
network_clock->SetCurrentTime(new_time);
}

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

@@ -221,6 +221,7 @@ void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) {
void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
std::shared_ptr<Applet> applet;
bool should_stop = false;
{
std::scoped_lock lk{m_lock};
@@ -231,10 +232,17 @@ void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
applet = it->second;
m_applets.erase(it);
should_stop = m_applets.empty();
}
// Terminate process.
applet->process->Terminate();
// If there were no applets left, stop emulation.
if (should_stop) {
m_system.Exit();
}
}
void AppletManager::CreateAndInsertByFrontendAppletParameters(

View File

@@ -60,13 +60,12 @@ void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
OutputParameters params{};
const auto res = applet->system_buffer_manager.WriteApplicationCaptureBuffer(
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
&params.was_written, &params.fbshare_layer_index);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(params.was_written);
rb.Push(params.fbshare_layer_index);
rb.PushRaw(params);
}
void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
@@ -80,13 +79,12 @@ void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestCon
LOG_WARNING(Service_AM, "(STUBBED) called");
OutputParameters params{};
const auto res = applet->system_buffer_manager.WriteApplicationCaptureBuffer(
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
&params.was_written, &params.fbshare_layer_index);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(params.was_written);
rb.Push(params.fbshare_layer_index);
rb.PushRaw(params);
}
void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) {
@@ -100,13 +98,12 @@ void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestCont
LOG_WARNING(Service_AM, "(STUBBED) called");
OutputParameters params{};
const auto res = applet->system_buffer_manager.WriteApplicationCaptureBuffer(
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
&params.was_written, &params.fbshare_layer_index);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(params.was_written);
rb.Push(params.fbshare_layer_index);
rb.PushRaw(params);
}
void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
@@ -120,13 +117,12 @@ void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContex
LOG_WARNING(Service_AM, "(STUBBED) called");
OutputParameters params{};
const auto res = applet->system_buffer_manager.WriteApplicationCaptureBuffer(
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
&params.was_written, &params.fbshare_layer_index);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(params.was_written);
rb.Push(params.fbshare_layer_index);
rb.PushRaw(params);
}
void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {

View File

@@ -115,15 +115,10 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
}
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
[[maybe_unused]] std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(
Core::System& system, std::shared_ptr<Applet> caller_applet, AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
if (program_id == 0) {
// Unknown applet
return {};
}
auto process = std::make_unique<Process>(system);
auto applet = std::make_shared<Applet>(system, std::move(process));

View File

@@ -60,8 +60,8 @@ void SystemBufferManager::SetWindowVisibility(bool visible) {
}
}
Result SystemBufferManager::WriteApplicationCaptureBuffer(bool* out_was_written,
s32* out_fbshare_layer_index) {
Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written,
s32* out_fbshare_layer_index) {
// TODO
R_SUCCEED();
}

View File

@@ -37,7 +37,7 @@ public:
void SetWindowVisibility(bool visible);
Result WriteApplicationCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
private:
Kernel::KProcess* m_process{};

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

@@ -35,10 +35,11 @@ public:
explicit IAudioRenderer(Core::System& system_, Manager& manager_,
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id)
u32 process_handle, Kernel::KProcess& process_,
u64 applet_resource_user_id, s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@@ -59,13 +60,15 @@ public:
// clang-format on
RegisterHandlers(functions);
impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
process.Open();
impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
applet_resource_user_id, session_id);
}
~IAudioRenderer() override {
impl->Finalize();
service_context.CloseEvent(rendered_event);
process.Close();
}
private:
@@ -235,6 +238,7 @@ private:
Kernel::KEvent* rendered_event;
Manager& manager;
std::unique_ptr<Renderer> impl;
Kernel::KProcess& process;
Common::ScratchBuffer<u8> output_buffer;
Common::ScratchBuffer<u8> performance_buffer;
};
@@ -455,7 +459,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
return;
}
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)};
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
const auto session_id{impl->GetSessionId()};
@@ -472,7 +476,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
transfer_memory_size, process_handle,
transfer_memory_size, process_handle, *process,
applet_resource_user_id, session_id);
}
@@ -522,7 +526,7 @@ void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
}
void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
LOG_ERROR(Service_Audio, "called. Implement me!");
}
void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {

View File

@@ -246,10 +246,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
static_service->GetStandardUserSystemClock(user_clock);
static_service->GetStandardUserSystemClock(&user_clock);
s64 posix_time{};
auto result = user_clock->GetCurrentTime(posix_time);
auto result = user_clock->GetCurrentTime(&posix_time);
if (result.IsError()) {
return result;
@@ -268,10 +268,10 @@ Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
static_service->GetStandardUserSystemClock(user_clock);
static_service->GetStandardUserSystemClock(&user_clock);
s64 posix_time{};
auto result = user_clock->GetCurrentTime(posix_time);
auto result = user_clock->GetCurrentTime(&posix_time);
if (result.IsError()) {
return result;
@@ -470,11 +470,11 @@ AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{};
static_service->GetTimeZoneService(timezone_service);
static_service->GetTimeZoneService(&timezone_service);
Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time);
timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time);
return {
.year = calendar_time.year,

View File

@@ -12,6 +12,109 @@
namespace Service {
// clang-format off
template <typename T>
struct UnwrapArg {
using Type = std::remove_cvref_t<T>;
};
template <typename T, int A>
struct UnwrapArg<InLargeData<T, A>> {
using Type = std::remove_cv_t<typename InLargeData<T, A>::Type>;
};
template <typename T>
struct UnwrapArg<Out<T>> {
using Type = AutoOut<typename Out<T>::Type>;
};
template <typename T>
struct UnwrapArg<OutCopyHandle<T>> {
using Type = AutoOut<typename OutCopyHandle<T>::Type>;
};
template <typename T>
struct UnwrapArg<OutMoveHandle<T>> {
using Type = AutoOut<typename OutMoveHandle<T>::Type>;
};
template <typename T, int A>
struct UnwrapArg<OutLargeData<T, A>> {
using Type = AutoOut<typename OutLargeData<T, A>::Type>;
};
enum class ArgumentType {
InProcessId,
InData,
InInterface,
InCopyHandle,
OutData,
OutInterface,
OutCopyHandle,
OutMoveHandle,
InBuffer,
InLargeData,
OutBuffer,
OutLargeData,
};
template <typename T>
struct ArgumentTraits;
template <>
struct ArgumentTraits<ClientProcessId> {
static constexpr ArgumentType Type = ArgumentType::InProcessId;
};
template <typename T>
struct ArgumentTraits<SharedPointer<T>> {
static constexpr ArgumentType Type = ArgumentType::InInterface;
};
template <typename T>
struct ArgumentTraits<InCopyHandle<T>> {
static constexpr ArgumentType Type = ArgumentType::InCopyHandle;
};
template <typename T>
struct ArgumentTraits<Out<SharedPointer<T>>> {
static constexpr ArgumentType Type = ArgumentType::OutInterface;
};
template <typename T>
struct ArgumentTraits<Out<T>> {
static constexpr ArgumentType Type = ArgumentType::OutData;
};
template <typename T>
struct ArgumentTraits<OutCopyHandle<T>> {
static constexpr ArgumentType Type = ArgumentType::OutCopyHandle;
};
template <typename T>
struct ArgumentTraits<OutMoveHandle<T>> {
static constexpr ArgumentType Type = ArgumentType::OutMoveHandle;
};
template <typename T, int A>
struct ArgumentTraits<Buffer<T, A>> {
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer;
};
template <typename T, int A>
struct ArgumentTraits<InLargeData<T, A>> {
static constexpr ArgumentType Type = ArgumentType::InLargeData;
};
template <typename T, int A>
struct ArgumentTraits<OutLargeData<T, A>> {
static constexpr ArgumentType Type = ArgumentType::OutLargeData;
};
template <typename T>
struct ArgumentTraits {
static constexpr ArgumentType Type = ArgumentType::InData;
};
struct RequestLayout {
u32 copy_handle_count;
u32 move_handle_count;
@@ -122,6 +225,8 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment");
static_assert(!RawDataFinished, "All input interface arguments must appear after raw data");
static_assert(!std::is_pointer_v<ArgType>, "Input raw data must not be a pointer");
static_assert(std::is_trivially_copyable_v<ArgType>, "Input raw data must be trivially copyable");
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
constexpr size_t ArgEnd = ArgOffset + ArgSize;
@@ -198,7 +303,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
constexpr size_t BufferSize = sizeof(ArgType);
// Clear the existing data.
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
@@ -237,27 +342,29 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable");
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
constexpr size_t ArgEnd = ArgOffset + ArgSize;
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize);
std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args).raw, ArgSize);
return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) {
if (is_domain) {
ctx.AddDomainObject(std::get<ArgIndex>(args));
ctx.AddDomainObject(std::get<ArgIndex>(args).raw);
} else {
ctx.AddMoveInterface(std::get<ArgIndex>(args));
ctx.AddMoveInterface(std::get<ArgIndex>(args).raw);
}
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
ctx.AddCopyObject(std::get<ArgIndex>(args));
ctx.AddCopyObject(std::get<ArgIndex>(args).raw);
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
ctx.AddMoveObject(std::get<ArgIndex>(args));
ctx.AddMoveObject(std::get<ArgIndex>(args).raw);
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
@@ -302,10 +409,10 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
}
const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false;
using MethodArguments = std::tuple<std::remove_reference_t<A>...>;
using MethodArguments = std::tuple<std::remove_cvref_t<A>...>;
OutTemporaryBuffers buffers{};
auto call_arguments = std::tuple<typename RemoveOut<A>::Type...>();
auto call_arguments = std::tuple<typename UnwrapArg<A>::Type...>();
// Read inputs.
const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2;

View File

@@ -12,22 +12,31 @@
namespace Service {
// clang-format off
template <typename T>
struct AutoOut {
T raw;
};
template <typename T>
class Out {
public:
using Type = T;
/* implicit */ Out(Type& t) : raw(&t) {}
~Out() = default;
/* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {}
/* implicit */ Out(Type* t) : raw(t) {}
Type* Get() const {
return raw;
}
Type& operator*() {
Type& operator*() const {
return *raw;
}
Type* operator->() const {
return raw;
}
private:
Type* raw;
};
@@ -35,6 +44,9 @@ private:
template <typename T>
using SharedPointer = std::shared_ptr<T>;
template <typename T>
using OutInterface = Out<SharedPointer<T>>;
struct ClientProcessId {
explicit operator bool() const {
return pid != 0;
@@ -101,17 +113,21 @@ class OutCopyHandle {
public:
using Type = T*;
/* implicit */ OutCopyHandle(Type& t) : raw(&t) {}
~OutCopyHandle() = default;
/* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {}
/* implicit */ OutCopyHandle(Type* t) : raw(t) {}
Type* Get() const {
return raw;
}
Type& operator*() {
Type& operator*() const {
return *raw;
}
Type* operator->() const {
return raw;
}
private:
Type* raw;
};
@@ -121,30 +137,34 @@ class OutMoveHandle {
public:
using Type = T*;
/* implicit */ OutMoveHandle(Type& t) : raw(&t) {}
~OutMoveHandle() = default;
/* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {}
/* implicit */ OutMoveHandle(Type* t) : raw(t) {}
Type* Get() const {
return raw;
}
Type& operator*() {
Type& operator*() const {
return *raw;
}
Type* operator->() const {
return raw;
}
private:
Type* raw;
};
enum BufferAttr : int {
BufferAttr_In = (1U << 0),
BufferAttr_Out = (1U << 1),
BufferAttr_HipcMapAlias = (1U << 2),
BufferAttr_HipcPointer = (1U << 3),
BufferAttr_FixedSize = (1U << 4),
BufferAttr_HipcAutoSelect = (1U << 5),
BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6),
BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7),
/* 0x01 */ BufferAttr_In = (1U << 0),
/* 0x02 */ BufferAttr_Out = (1U << 1),
/* 0x04 */ BufferAttr_HipcMapAlias = (1U << 2),
/* 0x08 */ BufferAttr_HipcPointer = (1U << 3),
/* 0x10 */ BufferAttr_FixedSize = (1U << 4),
/* 0x20 */ BufferAttr_HipcAutoSelect = (1U << 5),
/* 0x40 */ BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6),
/* 0x80 */ BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7),
};
template <typename T, int A>
@@ -172,123 +192,80 @@ struct Buffer : public std::span<T> {
}
};
template <BufferAttr A>
template <int A>
using InBuffer = Buffer<const u8, BufferAttr_In | A>;
template <typename T, BufferAttr A>
template <typename T, int A>
using InArray = Buffer<T, BufferAttr_In | A>;
template <BufferAttr A>
template <int A>
using OutBuffer = Buffer<u8, BufferAttr_Out | A>;
template <typename T, BufferAttr A>
template <typename T, int A>
using OutArray = Buffer<T, BufferAttr_Out | A>;
template <typename T, int A>
struct LargeData : public T {
class InLargeData {
public:
static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize");
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out");
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
static_assert((A & BufferAttr_Out) == 0, "InLargeData attr must not be Out");
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
using Type = const T;
/* implicit */ InLargeData(Type& t) : raw(&t) {}
~InLargeData() = default;
InLargeData& operator=(Type* rhs) {
raw = rhs;
return *this;
}
Type* Get() const {
return raw;
}
Type& operator*() const {
return *raw;
}
Type* operator->() const {
return raw;
}
explicit operator bool() const {
return raw != nullptr;
}
private:
Type* raw;
};
template <typename T, int A>
class OutLargeData {
public:
static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
static_assert((A & BufferAttr_In) == 0, "OutLargeData attr must not be In");
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
using Type = T;
/* implicit */ LargeData(const T& rhs) : T(rhs) {}
/* implicit */ LargeData() = default;
};
/* implicit */ OutLargeData(Type* t) : raw(t) {}
/* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {}
template <typename T, BufferAttr A>
using InLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_In | A>;
Type* Get() const {
return raw;
}
template <typename T, BufferAttr A>
using OutLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_Out | A>;
Type& operator*() const {
return *raw;
}
template <typename T>
struct RemoveOut {
using Type = std::remove_reference_t<T>;
};
Type* operator->() const {
return raw;
}
template <typename T>
struct RemoveOut<Out<T>> {
using Type = typename Out<T>::Type;
};
template <typename T>
struct RemoveOut<OutCopyHandle<T>> {
using Type = typename OutCopyHandle<T>::Type;
};
template <typename T>
struct RemoveOut<OutMoveHandle<T>> {
using Type = typename OutMoveHandle<T>::Type;
};
enum class ArgumentType {
InProcessId,
InData,
InInterface,
InCopyHandle,
OutData,
OutInterface,
OutCopyHandle,
OutMoveHandle,
InBuffer,
InLargeData,
OutBuffer,
OutLargeData,
};
template <typename T>
struct ArgumentTraits;
template <>
struct ArgumentTraits<ClientProcessId> {
static constexpr ArgumentType Type = ArgumentType::InProcessId;
};
template <typename T>
struct ArgumentTraits<SharedPointer<T>> {
static constexpr ArgumentType Type = ArgumentType::InInterface;
};
template <typename T>
struct ArgumentTraits<InCopyHandle<T>> {
static constexpr ArgumentType Type = ArgumentType::InCopyHandle;
};
template <typename T>
struct ArgumentTraits<Out<SharedPointer<T>>> {
static constexpr ArgumentType Type = ArgumentType::OutInterface;
};
template <typename T>
struct ArgumentTraits<Out<T>> {
static constexpr ArgumentType Type = ArgumentType::OutData;
};
template <typename T>
struct ArgumentTraits<OutCopyHandle<T>> {
static constexpr ArgumentType Type = ArgumentType::OutCopyHandle;
};
template <typename T>
struct ArgumentTraits<OutMoveHandle<T>> {
static constexpr ArgumentType Type = ArgumentType::OutMoveHandle;
};
template <typename T, int A>
struct ArgumentTraits<Buffer<T, A>> {
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer;
};
template <typename T, int A>
struct ArgumentTraits<LargeData<T, A>> {
static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutLargeData : ArgumentType::InLargeData;
};
template <typename T>
struct ArgumentTraits {
static constexpr ArgumentType Type = ArgumentType::InData;
private:
Type* raw;
};
// clang-format on
} // namespace Service
} // namespace Service

View File

@@ -41,7 +41,7 @@ bool AlarmWorker::GetClosestAlarmInfo(Service::PSC::Time::AlarmInfo& out_alarm_i
Service::PSC::Time::AlarmInfo alarm_info{};
s64 closest_time{};
auto res = m_time_m->GetClosestAlarmInfo(is_valid, alarm_info, closest_time);
auto res = m_time_m->GetClosestAlarmInfo(&is_valid, &alarm_info, &closest_time);
ASSERT(res == ResultSuccess);
if (is_valid) {
@@ -76,6 +76,7 @@ void AlarmWorker::OnPowerStateChanged() {
Result AlarmWorker::AttachToClosestAlarmEvent() {
m_time_m->GetClosestAlarmUpdatedEvent(&m_event);
R_SUCCEED();
}

View File

@@ -26,7 +26,7 @@ public:
void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m);
Kernel::KEvent& GetEvent() {
Kernel::KReadableEvent& GetEvent() {
return *m_event;
}
@@ -44,7 +44,7 @@ private:
KernelHelpers::ServiceContext m_ctx;
std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m;
Kernel::KEvent* m_event{};
Kernel::KReadableEvent* m_event{};
Kernel::KEvent* m_timer_event{};
std::shared_ptr<Core::Timing::EventType> m_timer_timing_event;
StandardSteadyClockResource& m_steady_clock_resource;

View File

@@ -13,8 +13,8 @@ void FileTimestampWorker::SetFilesystemPosixTime() {
Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
if (m_initialized && m_system_clock->GetCurrentTime(time) == ResultSuccess &&
m_time_zone->ToCalendarTimeWithMyRule(calendar_time, additional_info, time) ==
if (m_initialized && m_system_clock->GetCurrentTime(&time) == ResultSuccess &&
m_time_zone->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, time) ==
ResultSuccess) {
// TODO IFileSystemProxy::SetCurrentPosixTime
}

View File

@@ -79,18 +79,18 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN
auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
Service::PSC::Time::LocationName configured_name{};
std::memcpy(configured_name.name.data(), configured_zone.data(),
std::min(configured_name.name.size(), configured_zone.size()));
std::memcpy(configured_name.data(), configured_zone.data(),
std::min(configured_name.size(), configured_zone.size()));
if (!IsTimeZoneBinaryValid(configured_name)) {
configured_zone = Common::TimeZone::FindSystemTimeZone();
configured_name = {};
std::memcpy(configured_name.name.data(), configured_zone.data(),
std::min(configured_name.name.size(), configured_zone.size()));
std::memcpy(configured_name.data(), configured_zone.data(),
std::min(configured_name.size(), configured_zone.size()));
}
ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
configured_name.name.data());
configured_name.data());
return configured_name;
}
@@ -103,7 +103,7 @@ TimeManager::TimeManager(Core::System& system)
m_time_m =
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
auto res = m_time_m->GetStaticServiceAsServiceManager(m_time_sm);
auto res = m_time_m->GetStaticServiceAsServiceManager(&m_time_sm);
ASSERT(res == ResultSuccess);
m_set_sys =
@@ -114,10 +114,10 @@ TimeManager::TimeManager(Core::System& system)
m_worker.Initialize(m_time_sm, m_set_sys);
res = m_time_sm->GetStandardUserSystemClock(m_file_timestamp_worker.m_system_clock);
res = m_time_sm->GetStandardUserSystemClock(&m_file_timestamp_worker.m_system_clock);
ASSERT(res == ResultSuccess);
res = m_time_sm->GetTimeZoneService(m_file_timestamp_worker.m_time_zone);
res = m_time_sm->GetTimeZoneService(&m_file_timestamp_worker.m_time_zone);
ASSERT(res == ResultSuccess);
res = SetupStandardSteadyClockCore();
@@ -161,8 +161,8 @@ TimeManager::TimeManager(Core::System& system)
automatic_correction_time_point);
ASSERT(res == ResultSuccess);
res = m_time_m->SetupStandardUserSystemClockCore(automatic_correction_time_point,
is_automatic_correction_enabled);
res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled,
automatic_correction_time_point);
ASSERT(res == ResultSuccess);
res = m_time_m->SetupEphemeralNetworkSystemClockCore();
@@ -184,12 +184,12 @@ TimeManager::TimeManager(Core::System& system)
m_file_timestamp_worker.m_initialized = true;
s64 system_clock_time{};
if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(system_clock_time) ==
if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(&system_clock_time) ==
ResultSuccess) {
Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo calendar_additional{};
if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule(
calendar_time, calendar_additional, system_clock_time) == ResultSuccess) {
&calendar_time, &calendar_additional, system_clock_time) == ResultSuccess) {
// TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time,
// calendar_additional.ut_offset)
}
@@ -228,10 +228,9 @@ Result TimeManager::SetupStandardSteadyClockCore() {
m_set_sys->SetExternalSteadyClockSourceId(clock_source_id);
}
res = m_time_m->SetupStandardSteadyClockCore(clock_source_id, m_steady_clock_resource.GetTime(),
external_steady_clock_internal_offset_ns,
standard_steady_clock_test_offset_ns,
reset_detected);
res = m_time_m->SetupStandardSteadyClockCore(
reset_detected, clock_source_id, m_steady_clock_resource.GetTime(),
external_steady_clock_internal_offset_ns, standard_steady_clock_test_offset_ns);
ASSERT(res == ResultSuccess);
R_SUCCEED();
}
@@ -243,14 +242,15 @@ Result TimeManager::SetupTimeZoneServiceCore() {
auto configured_zone = GetTimeZoneString(name);
if (configured_zone.name != name.name) {
if (configured_zone != name) {
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
name = configured_zone;
std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
m_time_sm->GetStandardLocalSystemClock(local_clock);
m_time_sm->GetStandardLocalSystemClock(&local_clock);
Service::PSC::Time::SystemClockContext context{};
local_clock->GetSystemClockContext(context);
local_clock->GetSystemClockContext(&context);
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point);
}
@@ -267,7 +267,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
res = GetTimeZoneRule(rule_buffer, rule_size, name);
ASSERT(res == ResultSuccess);
res = m_time_m->SetupTimeZoneServiceCore(name, time_point, rule_version, location_count,
res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point,
rule_buffer);
ASSERT(res == ResultSuccess);

View File

@@ -3,9 +3,11 @@
#include <chrono>
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/glue/time/file_timestamp_worker.h"
#include "core/hle/service/glue/time/static.h"
#include "core/hle/service/psc/time/errors.h"
@@ -41,25 +43,25 @@ StaticService::StaticService(Core::System& system_,
time->m_steady_clock_resource} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
{1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
{2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
{3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
{4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
{5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
{20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
{50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
{51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
{100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
{200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
{401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
{500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
};
// clang-format on
@@ -71,314 +73,80 @@ StaticService::StaticService(Core::System& system_,
if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock &&
!m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location &&
!m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) {
m_time_m->GetStaticServiceAsAdmin(m_wrapped_service);
m_time_m->GetStaticServiceAsAdmin(&m_wrapped_service);
} else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock &&
!m_setup_info.can_write_network_clock &&
!m_setup_info.can_write_timezone_device_location &&
!m_setup_info.can_write_steady_clock &&
!m_setup_info.can_write_uninitialized_clock) {
m_time_m->GetStaticServiceAsUser(m_wrapped_service);
m_time_m->GetStaticServiceAsUser(&m_wrapped_service);
} else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock &&
!m_setup_info.can_write_network_clock &&
!m_setup_info.can_write_timezone_device_location &&
m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) {
m_time_m->GetStaticServiceAsRepair(m_wrapped_service);
m_time_m->GetStaticServiceAsRepair(&m_wrapped_service);
} else {
UNREACHABLE();
}
auto res = m_wrapped_service->GetTimeZoneService(m_time_zone);
auto res = m_wrapped_service->GetTimeZoneService(&m_time_zone);
ASSERT(res == ResultSuccess);
}
void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
auto res = GetStandardUserSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
}
void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
auto res = GetStandardNetworkSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
}
void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<Service::PSC::Time::SteadyClock> service{};
auto res = GetStandardSteadyClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface(std::move(service));
}
void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<TimeZoneService> service{};
auto res = GetTimeZoneService(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface(std::move(service));
}
void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
auto res = GetStandardLocalSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
}
void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<Service::PSC::Time::SystemClock> service{};
auto res = GetEphemeralNetworkSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
}
void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KSharedMemory* shared_memory{};
auto res = GetSharedMemoryNativeHandle(&shared_memory);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(shared_memory);
}
void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto offset_ns{rp.Pop<s64>()};
auto res = SetStandardSteadyClockInternalOffset(offset_ns);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
s64 rtc_value{};
auto res = GetStandardSteadyClockRtcValue(rtc_value);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(rtc_value);
}
void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
bool is_enabled{};
auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push<bool>(is_enabled);
}
void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto automatic_correction{rp.Pop<bool>()};
auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
s32 initial_year{};
auto res = GetStandardUserSystemClockInitialYear(initial_year);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(initial_year);
}
void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
bool is_sufficient{};
auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push<bool>(is_sufficient);
}
void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Service::PSC::Time::SteadyClockTimePoint time_point{};
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
IPC::ResponseBuilder rb{ctx,
2 + sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
}
void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
s64 time{};
auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push<s64>(time);
}
void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto type{rp.PopEnum<Service::PSC::Time::TimeType>()};
Service::PSC::Time::ClockSnapshot snapshot{};
auto res = GetClockSnapshot(snapshot, type);
ctx.WriteBuffer(snapshot);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto clock_type{rp.PopEnum<Service::PSC::Time::TimeType>()};
[[maybe_unused]] auto alignment{rp.Pop<u32>()};
auto user_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
auto network_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
Service::PSC::Time::ClockSnapshot snapshot{};
auto res =
GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
ctx.WriteBuffer(snapshot);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Service::PSC::Time::ClockSnapshot a{};
Service::PSC::Time::ClockSnapshot b{};
auto a_buffer{ctx.ReadBuffer(0)};
auto b_buffer{ctx.ReadBuffer(1)};
std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
s64 difference{};
auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(difference);
}
void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Service::PSC::Time::ClockSnapshot a{};
Service::PSC::Time::ClockSnapshot b{};
auto a_buffer{ctx.ReadBuffer(0)};
auto b_buffer{ctx.ReadBuffer(1)};
std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
s64 time{};
auto res = CalculateSpanBetween(time, a, b);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(time);
}
// =============================== Implementations ===========================
Result StaticService::GetStandardUserSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
OutInterface<Service::PSC::Time::SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service));
}
Result StaticService::GetStandardNetworkSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
OutInterface<Service::PSC::Time::SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service));
}
Result StaticService::GetStandardSteadyClock(
std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service) {
OutInterface<Service::PSC::Time::SteadyClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service));
}
Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
out_service = std::make_shared<TimeZoneService>(m_system, m_file_timestamp_worker,
m_setup_info.can_write_timezone_device_location,
m_time_zone);
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
LOG_DEBUG(Service_Time, "called.");
*out_service = std::make_shared<TimeZoneService>(
m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location,
m_time_zone);
R_SUCCEED();
}
Result StaticService::GetStandardLocalSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
OutInterface<Service::PSC::Time::SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service));
}
Result StaticService::GetEphemeralNetworkSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
OutInterface<Service::PSC::Time::SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service));
}
Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
Result StaticService::GetSharedMemoryNativeHandle(
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory));
}
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
LOG_DEBUG(Service_Time, "called. offset_ns={}", offset_ns);
R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied);
R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset(
@@ -386,62 +154,92 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()));
}
Result StaticService::GetStandardSteadyClockRtcValue(s64& out_rtc_value) {
R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(out_rtc_value));
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value));
}
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
bool& out_automatic_correction) {
Out<bool> out_automatic_correction) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction);
});
R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled(
out_automatic_correction));
}
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
bool automatic_correction) {
LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled(
automatic_correction));
}
Result StaticService::GetStandardUserSystemClockInitialYear(s32& out_year) {
out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); });
*out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
R_SUCCEED();
}
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) {
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient));
}
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Service::PSC::Time::SteadyClockTimePoint& out_time_point) {
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
out_time_point));
}
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
s64& out_time, Service::PSC::Time::SystemClockContext& context) {
Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context));
}
Result StaticService::GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot,
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot,
Service::PSC::Time::TimeType type) {
SCOPE_EXIT(
{ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type));
}
Result StaticService::GetClockSnapshotFromSystemClockContext(
Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
Service::PSC::Time::SystemClockContext& user_context,
Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type) {
R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(out_snapshot, user_context,
network_context, type));
Service::PSC::Time::SystemClockContext& network_context) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time,
"called. type={} out_snapshot={} user_context={} network_context={}", type,
*out_snapshot, user_context, network_context);
});
R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(
type, out_snapshot, user_context, network_context));
}
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(
s64& out_time, Service::PSC::Time::ClockSnapshot& a, Service::PSC::Time::ClockSnapshot& b) {
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time,
InClockSnapshot a,
InClockSnapshot b) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b));
}
Result StaticService::CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
Service::PSC::Time::ClockSnapshot& b) {
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
InClockSnapshot b) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b));
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include "common/common_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/glue/time/manager.h"
#include "core/hle/service/glue/time/time_zone.h"
#include "core/hle/service/psc/time/common.h"
@@ -29,6 +30,10 @@ class FileTimestampWorker;
class StandardSteadyClockResource;
class StaticService final : public ServiceFramework<StaticService> {
using InClockSnapshot = InLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>;
using OutClockSnapshot =
OutLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>;
public:
explicit StaticService(Core::System& system,
Service::PSC::Time::StaticServiceSetupInfo setup_info,
@@ -36,65 +41,34 @@ public:
~StaticService() override = default;
Result GetStandardUserSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetStandardNetworkSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetStandardSteadyClock(std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service);
Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
Result GetStandardLocalSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetStandardUserSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
Result GetStandardNetworkSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
Result GetStandardSteadyClock(OutInterface<Service::PSC::Time::SteadyClock> out_service);
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
Result GetStandardLocalSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
Result GetEphemeralNetworkSystemClock(
std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
Result SetStandardSteadyClockInternalOffset(s64 offset);
Result GetStandardSteadyClockRtcValue(s64& out_rtc_value);
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_automatic_correction);
OutInterface<Service::PSC::Time::SystemClock> out_service);
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
Result GetStandardUserSystemClockInitialYear(s32& out_year);
Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
Service::PSC::Time::SteadyClockTimePoint& out_time_point);
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result CalculateMonotonicSystemClockBaseTimePoint(
s64& out_time, Service::PSC::Time::SystemClockContext& context);
Result GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::TimeType type);
Out<s64> out_time, Service::PSC::Time::SystemClockContext& context);
Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type);
Result GetClockSnapshotFromSystemClockContext(
Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
Service::PSC::Time::SystemClockContext& user_context,
Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type);
Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
Service::PSC::Time::ClockSnapshot& a,
Service::PSC::Time::ClockSnapshot& b);
Result CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
Service::PSC::Time::ClockSnapshot& b);
Service::PSC::Time::SystemClockContext& network_context);
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
InClockSnapshot a, InClockSnapshot b);
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
private:
Result GetClockSnapshotImpl(Service::PSC::Time::ClockSnapshot& out_snapshot,
Service::PSC::Time::SystemClockContext& user_context,
Service::PSC::Time::SystemClockContext& network_context,
Service::PSC::Time::TimeType type);
void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
void Handle_GetTimeZoneService(HLERequestContext& ctx);
void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
void Handle_GetClockSnapshot(HLERequestContext& ctx);
void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
void Handle_CalculateSpanBetween(HLERequestContext& ctx);
Core::System& m_system;
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;

View File

@@ -3,8 +3,10 @@
#include <chrono>
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/glue/time/file_timestamp_worker.h"
#include "core/hle/service/glue/time/time_zone.h"
#include "core/hle/service/glue/time/time_zone_binary.h"
@@ -28,20 +30,20 @@ TimeZoneService::TimeZoneService(
m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
{1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
{2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
{3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
{4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
{5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
{6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
{7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
{8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
{20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
{101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
{201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
{202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
};
// clang-format on
RegisterHandlers(functions);
@@ -53,220 +55,16 @@ TimeZoneService::TimeZoneService(
TimeZoneService::~TimeZoneService() = default;
void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::GetDeviceLocationName(
Out<Service::PSC::Time::LocationName> out_location_name) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
Service::PSC::Time::LocationName name{};
auto res = GetDeviceLocationName(name);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<Service::PSC::Time::LocationName>(name);
}
void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
auto res = SetDeviceLocation(name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
u32 count{};
auto res = GetTotalLocationNameCount(count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
}
void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto index{rp.Pop<u32>()};
auto max_names{ctx.GetWriteBufferSize() / sizeof(Service::PSC::Time::LocationName)};
std::vector<Service::PSC::Time::LocationName> names{};
u32 count{};
auto res = LoadLocationNameList(count, names, max_names, index);
ctx.WriteBuffer(names);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
}
void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
Tz::Rule rule{};
auto res = LoadTimeZoneRule(rule, name);
ctx.WriteBuffer(rule);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Service::PSC::Time::RuleVersion rule_version{};
auto res = GetTimeZoneRuleVersion(rule_version);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::RuleVersion) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<Service::PSC::Time::RuleVersion>(rule_version);
}
void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Service::PSC::Time::LocationName name{};
Service::PSC::Time::SteadyClockTimePoint time_point{};
auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
IPC::ResponseBuilder rb{ctx,
2 + (sizeof(Service::PSC::Time::LocationName) / sizeof(u32)) +
(sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32))};
rb.Push(res);
rb.PushRaw<Service::PSC::Time::LocationName>(name);
rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
}
void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
auto res = SetDeviceLocationNameWithTimeZoneRule();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(Service::PSC::Time::ResultNotImplemented);
}
void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetDeviceLocationNameOperationEventReadableHandle(&event);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(event->GetReadableEvent());
}
void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto time{rp.Pop<s64>()};
auto rule_buffer{ctx.ReadBuffer()};
Tz::Rule rule{};
std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
IPC::ResponseBuilder rb{ctx,
2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) +
(sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))};
rb.Push(res);
rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time);
rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info);
}
void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto time{rp.Pop<s64>()};
LOG_DEBUG(Service_Time, "called. time={}", time);
Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
IPC::ResponseBuilder rb{ctx,
2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) +
(sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))};
rb.Push(res);
rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time);
rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info);
}
void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()};
LOG_DEBUG(Service_Time, "called. calendar year {} month {} day {} hour {} minute {} second {}",
calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute,
calendar.second);
auto binary{ctx.ReadBuffer()};
Tz::Rule rule{};
std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
u32 count{};
std::array<s64, 2> times{};
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
auto res = ToPosixTime(count, times, times_count, calendar, rule);
ctx.WriteBuffer(times);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
}
void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()};
u32 count{};
std::array<s64, 2> times{};
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
ctx.WriteBuffer(times);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
}
// =============================== Implementations ===========================
Result TimeZoneService::GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name) {
R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name));
}
Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& location_name) {
Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) {
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
@@ -282,7 +80,7 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca
Service::PSC::Time::SteadyClockTimePoint time_point{};
Service::PSC::Time::LocationName name{};
R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(time_point, name));
R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(&name, &time_point));
m_set_sys->SetDeviceTimeZoneLocationName(name);
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point);
@@ -294,19 +92,27 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca
R_SUCCEED();
}
Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) {
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count));
}
Result TimeZoneService::LoadLocationNameList(
u32& out_count, std::vector<Service::PSC::Time::LocationName>& out_names, size_t max_names,
u32 index) {
Out<u32> out_count,
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",
index, *out_count, out_names[0], out_names[1]);
});
std::scoped_lock l{m_mutex};
R_RETURN(GetTimeZoneLocationList(out_count, out_names, max_names, index));
R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
}
Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule,
Service::PSC::Time::LocationName& name) {
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) {
LOG_DEBUG(Service_Time, "called. name={}", name);
std::scoped_lock l{m_mutex};
std::span<const u8> binary{};
size_t binary_size{};
@@ -314,23 +120,43 @@ Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule,
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
}
Result TimeZoneService::GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
Result TimeZoneService::GetTimeZoneRuleVersion(
Out<Service::PSC::Time::RuleVersion> out_rule_version) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version));
}
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
Service::PSC::Time::SteadyClockTimePoint& out_time_point,
Service::PSC::Time::LocationName& location_name) {
R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(out_time_point, location_name));
Out<Service::PSC::Time::LocationName> location_name,
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name,
*out_time_point);
});
R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point));
}
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule() {
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
Service::PSC::Time::LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
R_RETURN(Service::PSC::Time::ResultNotImplemented);
}
Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
InBuffer<BufferAttr_HipcAutoSelect> binary) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(Service::PSC::Time::ResultNotImplemented);
}
Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
Kernel::KEvent** out_event) {
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
if (!operation_event_initialized) {
operation_event_initialized = false;
@@ -342,34 +168,59 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
g_list_nodes.push_back(m_operation_event);
}
*out_event = m_operation_event.m_event;
*out_event = &m_operation_event.m_event->GetReadableEvent();
R_SUCCEED();
}
Result TimeZoneService::ToCalendarTime(
Service::PSC::Time::CalendarTime& out_calendar_time,
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule) {
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
});
R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
}
Result TimeZoneService::ToCalendarTimeWithMyRule(
Service::PSC::Time::CalendarTime& out_calendar_time,
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time) {
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
});
R_RETURN(
m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
}
Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
u32 out_times_count,
Service::PSC::Time::CalendarTime& calendar_time,
Tz::Rule& rule) {
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count,
Service::PSC::Time::CalendarTime& calendar_time, InRule rule) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
"out_times_count={}",
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
});
R_RETURN(
m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
}
Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
u32 out_times_count,
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count,
Service::PSC::Time::CalendarTime& calendar_time) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
"out_times_count={}",
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
});
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count,
calendar_time));
}

View File

@@ -8,6 +8,7 @@
#include <span>
#include <vector>
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/server_manager.h"
@@ -33,6 +34,9 @@ namespace Service::Glue::Time {
class FileTimestampWorker;
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
public:
explicit TimeZoneService(
Core::System& system, FileTimestampWorker& file_timestamp_worker,
@@ -41,46 +45,37 @@ public:
~TimeZoneService() override;
Result GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name);
Result SetDeviceLocation(Service::PSC::Time::LocationName& location_name);
Result GetTotalLocationNameCount(u32& out_count);
Result LoadLocationNameList(u32& out_count,
std::vector<Service::PSC::Time::LocationName>& out_names,
size_t max_names, u32 index);
Result LoadTimeZoneRule(Tz::Rule& out_rule, Service::PSC::Time::LocationName& name);
Result GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version);
Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name);
Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name);
Result GetTotalLocationNameCount(Out<u32> out_count);
Result LoadLocationNameList(
Out<u32> out_count,
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index);
Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name);
Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version);
Result GetDeviceLocationNameAndUpdatedTime(
Service::PSC::Time::SteadyClockTimePoint& out_time_point,
Service::PSC::Time::LocationName& location_name);
Result SetDeviceLocationNameWithTimeZoneRule();
Result GetDeviceLocationNameOperationEventReadableHandle(Kernel::KEvent** out_event);
Result ToCalendarTime(Service::PSC::Time::CalendarTime& out_calendar_time,
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time,
Tz::Rule& rule);
Result ToCalendarTimeWithMyRule(Service::PSC::Time::CalendarTime& out_calendar_time,
Service::PSC::Time::CalendarAdditionalInfo& out_additional_info,
s64 time);
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
Service::PSC::Time::CalendarTime& calendar_time, Tz::Rule& rule);
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
Out<Service::PSC::Time::LocationName> location_name,
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name,
InBuffer<BufferAttr_HipcAutoSelect> binary);
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
Result GetDeviceLocationNameOperationEventReadableHandle(
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result ToCalendarTime(Out<Service::PSC::Time::CalendarTime> out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info,
s64 time, InRule rule);
Result ToCalendarTimeWithMyRule(
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time);
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time,
InRule rule);
Result ToPosixTimeWithMyRule(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count,
Service::PSC::Time::CalendarTime& calendar_time);
private:
void Handle_GetDeviceLocationName(HLERequestContext& ctx);
void Handle_SetDeviceLocationName(HLERequestContext& ctx);
void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
void Handle_LoadLocationNameList(HLERequestContext& ctx);
void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
void Handle_ToCalendarTime(HLERequestContext& ctx);
void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
void Handle_ToPosixTime(HLERequestContext& ctx);
void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
Core::System& m_system;
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;

View File

@@ -103,7 +103,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName
return;
}
// out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name);
out_path = fmt::format("/zoneinfo/{}", name.name.data());
out_path = fmt::format("/zoneinfo/{}", name.data());
}
bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) {
@@ -169,7 +169,7 @@ Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
}
Result GetTimeZoneLocationList(u32& out_count,
std::vector<Service::PSC::Time::LocationName>& out_names,
std::span<Service::PSC::Time::LocationName> out_names,
size_t max_names, u32 index) {
std::string path{};
GetTimeZoneBinaryListPath(path);
@@ -193,7 +193,7 @@ Result GetTimeZoneLocationList(u32& out_count,
if (chr == '\n') {
if (name_count >= index) {
out_names.push_back(current_name);
out_names[out_count] = current_name;
out_count++;
if (out_count >= max_names) {
break;
@@ -209,10 +209,9 @@ Result GetTimeZoneLocationList(u32& out_count,
break;
}
R_UNLESS(current_name_len <= current_name.name.size() - 2,
Service::PSC::Time::ResultFailed);
R_UNLESS(current_name_len <= current_name.size() - 2, Service::PSC::Time::ResultFailed);
current_name.name[current_name_len++] = chr;
current_name[current_name_len++] = chr;
}
R_SUCCEED();

View File

@@ -26,7 +26,7 @@ Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version);
Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
Service::PSC::Time::LocationName& name);
Result GetTimeZoneLocationList(u32& out_count,
std::vector<Service::PSC::Time::LocationName>& out_names,
std::span<Service::PSC::Time::LocationName> out_names,
size_t max_names, u32 index);
} // namespace Service::Glue::Time

View File

@@ -38,11 +38,12 @@ T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
FileTimestampWorker& file_timestamp_worker)
: m_system{system}, m_ctx{m_system, "Glue:58"}, m_event{m_ctx.CreateEvent("Glue:58:Event")},
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent(
"Glue:TimeWorker:Event")},
m_steady_clock_resource{steady_clock_resource},
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
"Glue:58:SteadyClockTimerEvent")},
m_timer_file_system{m_ctx.CreateEvent("Glue:58:FileTimeTimerEvent")},
"Glue:TimeWorker:SteadyClockTimerEvent")},
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
g_ig_report_network_clock_context_set = false;
g_report_network_clock_context = {};
@@ -113,17 +114,17 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
std::chrono::nanoseconds(fs_notify_time_ns),
m_timer_file_system_timing_event);
auto res = m_time_sm->GetStandardLocalSystemClock(m_local_clock);
auto res = m_time_sm->GetStandardLocalSystemClock(&m_local_clock);
ASSERT(res == ResultSuccess);
res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event);
ASSERT(res == ResultSuccess);
res = m_time_sm->GetStandardNetworkSystemClock(m_network_clock);
res = m_time_sm->GetStandardNetworkSystemClock(&m_network_clock);
ASSERT(res == ResultSuccess);
res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event);
ASSERT(res == ResultSuccess);
res = m_time_sm->GetEphemeralNetworkSystemClock(m_ephemeral_clock);
res = m_time_sm->GetEphemeralNetworkSystemClock(&m_ephemeral_clock);
ASSERT(res == ResultSuccess);
res =
m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event);
@@ -183,22 +184,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
// TODO
// AddWaiter(gIPmModuleService::GetEvent(), 1);
AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange);
AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange);
} else {
AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
// TODO
// AddWaiter(gIPmModuleService::GetEvent(), 1);
AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange);
AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange);
AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms);
AddWaiter(&m_local_clock_event->GetReadableEvent(), EventType::UpdateLocalSystemClock);
AddWaiter(&m_network_clock_event->GetReadableEvent(),
EventType::UpdateNetworkSystemClock);
AddWaiter(&m_ephemeral_clock_event->GetReadableEvent(),
EventType::UpdateEphemeralSystemClock);
AddWaiter(m_local_clock_event, EventType::UpdateLocalSystemClock);
AddWaiter(m_network_clock_event, EventType::UpdateNetworkSystemClock);
AddWaiter(m_ephemeral_clock_event, EventType::UpdateEphemeralSystemClock);
AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock);
AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp);
AddWaiter(&m_standard_user_auto_correct_clock_event->GetReadableEvent(),
EventType::AutoCorrect);
AddWaiter(m_standard_user_auto_correct_clock_event, EventType::AutoCorrect);
}
s32 out_index{-1};
@@ -237,7 +235,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
m_local_clock_event->Clear();
Service::PSC::Time::SystemClockContext context{};
auto res = m_local_clock->GetSystemClockContext(context);
auto res = m_local_clock->GetSystemClockContext(&context);
ASSERT(res == ResultSuccess);
m_set_sys->SetUserSystemClockContext(context);
@@ -248,12 +246,12 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
case EventType::UpdateNetworkSystemClock: {
m_network_clock_event->Clear();
Service::PSC::Time::SystemClockContext context{};
auto res = m_network_clock->GetSystemClockContext(context);
auto res = m_network_clock->GetSystemClockContext(&context);
ASSERT(res == ResultSuccess);
m_set_sys->SetNetworkSystemClockContext(context);
s64 time{};
if (m_network_clock->GetCurrentTime(time) != ResultSuccess) {
if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) {
break;
}
@@ -275,13 +273,13 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
m_ephemeral_clock_event->Clear();
Service::PSC::Time::SystemClockContext context{};
auto res = m_ephemeral_clock->GetSystemClockContext(context);
auto res = m_ephemeral_clock->GetSystemClockContext(&context);
if (res != ResultSuccess) {
break;
}
s64 time{};
res = m_ephemeral_clock->GetCurrentTime(time);
res = m_ephemeral_clock->GetCurrentTime(&time);
if (res != ResultSuccess) {
break;
}
@@ -317,11 +315,11 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
bool automatic_correction{};
auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled(
automatic_correction);
&automatic_correction);
ASSERT(res == ResultSuccess);
Service::PSC::Time::SteadyClockTimePoint time_point{};
res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point);
ASSERT(res == ResultSuccess);
m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction);

View File

@@ -49,10 +49,10 @@ private:
std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock;
StandardSteadyClockResource& m_steady_clock_resource;
FileTimestampWorker& m_file_timestamp_worker;
Kernel::KEvent* m_local_clock_event{};
Kernel::KEvent* m_network_clock_event{};
Kernel::KEvent* m_ephemeral_clock_event{};
Kernel::KEvent* m_standard_user_auto_correct_clock_event{};
Kernel::KReadableEvent* m_local_clock_event{};
Kernel::KReadableEvent* m_network_clock_event{};
Kernel::KReadableEvent* m_ephemeral_clock_event{};
Kernel::KReadableEvent* m_standard_user_auto_correct_clock_event{};
Kernel::KEvent* m_timer_steady_clock{};
std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event;
Kernel::KEvent* m_timer_file_system{};

View File

@@ -1405,7 +1405,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{};
static_service->GetTimeZoneService(timezone_service);
static_service->GetTimeZoneService(&timezone_service);
Service::PSC::Time::CalendarTime calendar_time{};
Service::PSC::Time::CalendarAdditionalInfo additional_info{};
@@ -1416,7 +1416,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
amiibo_date.SetMonth(1);
amiibo_date.SetDay(1);
if (timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time) ==
if (timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time) ==
ResultSuccess) {
amiibo_date.SetYear(calendar_time.year);
amiibo_date.SetMonth(calendar_time.month);
@@ -1431,10 +1431,10 @@ s64 NfcDevice::GetCurrentPosixTime() const {
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
static_service->GetStandardSteadyClock(steady_clock);
static_service->GetStandardSteadyClock(&steady_clock);
Service::PSC::Time::SteadyClockTimePoint time_point{};
R_ASSERT(steady_clock->GetCurrentTimePoint(time_point));
R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
return time_point.time_point;
}

View File

@@ -91,10 +91,10 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max
true);
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
static_service->GetStandardSteadyClock(steady_clock);
static_service->GetStandardSteadyClock(&steady_clock);
Service::PSC::Time::SteadyClockTimePoint time_point{};
R_ASSERT(steady_clock->GetCurrentTimePoint(time_point));
R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
const s64 elapsed_time = time_point.time_point - time_since_last_error;
if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
@@ -754,10 +754,10 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
static_service->GetStandardSteadyClock(steady_clock);
static_service->GetStandardSteadyClock(&steady_clock);
Service::PSC::Time::SteadyClockTimePoint time_point{};
R_ASSERT(steady_clock->GetCurrentTimePoint(time_point));
R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
time_since_last_error = time_point.time_point;
}

View File

@@ -5,6 +5,7 @@
#include <array>
#include <chrono>
#include <fmt/format.h>
#include "common/common_types.h"
#include "common/intrusive_list.h"
@@ -21,8 +22,14 @@ class System;
namespace Service::PSC::Time {
using ClockSourceId = Common::UUID;
enum class TimeType : u8 {
UserSystemClock = 0,
NetworkSystemClock = 1,
LocalSystemClock = 2,
};
struct SteadyClockTimePoint {
constexpr bool IdMatches(SteadyClockTimePoint& other) {
constexpr bool IdMatches(const SteadyClockTimePoint& other) const {
return clock_source_id == other.clock_source_id;
}
bool operator==(const SteadyClockTimePoint& other) const = default;
@@ -42,12 +49,6 @@ struct SystemClockContext {
static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!");
static_assert(std::is_trivial_v<SystemClockContext>);
enum class TimeType : u8 {
UserSystemClock,
NetworkSystemClock,
LocalSystemClock,
};
struct CalendarTime {
s16 year;
s8 month;
@@ -67,14 +68,10 @@ struct CalendarAdditionalInfo {
};
static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!");
struct LocationName {
std::array<char, 36> name;
};
using LocationName = std::array<char, 0x24>;
static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!");
struct RuleVersion {
std::array<char, 16> version;
};
using RuleVersion = std::array<char, 0x10>;
static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!");
struct ClockSnapshot {
@@ -152,8 +149,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) {
return std::chrono::nanoseconds(a + b);
}
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a,
SteadyClockTimePoint& b) {
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a,
const SteadyClockTimePoint& b) {
R_UNLESS(out_seconds, ResultInvalidArgument);
R_UNLESS(a.IdMatches(b), ResultInvalidArgument);
R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(),
@@ -166,3 +163,111 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTi
}
} // namespace Service::PSC::Time
template <>
struct fmt::formatter<Service::PSC::Time::TimeType> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(Service::PSC::Time::TimeType type, FormatContext& ctx) {
const string_view name = [type] {
using Service::PSC::Time::TimeType;
switch (type) {
case TimeType::UserSystemClock:
return "UserSystemClock";
case TimeType::NetworkSystemClock:
return "NetworkSystemClock";
case TimeType::LocalSystemClock:
return "LocalSystemClock";
}
return "Invalid";
}();
return formatter<string_view>::format(name, ctx);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset,
context.steady_time_point.time_point);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month,
calendar.year, calendar.hour, calendar.minute, calendar.second);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo>
: fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}",
additional.day_of_week, additional.day_of_year,
additional.name.data(), additional.is_dst, additional.ut_offset);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
std::string_view n{name.data(), name.size()};
return formatter<string_view>::format(n, ctx);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
std::string_view v{version.data(), version.size()};
return formatter<string_view>::format(v, ctx);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
return fmt::format_to(
ctx.out(),
"user_context={} network_context={} user_time={} network_time={} user_calendar_time={} "
"network_calendar_time={} user_calendar_additional_time={} "
"network_calendar_additional_time={} steady_clock_time_point={} location={} "
"is_automatic_correction_enabled={} type={}",
snapshot.user_context, snapshot.network_context, snapshot.user_time,
snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
snapshot.steady_clock_time_point, snapshot.location_name,
snapshot.is_automatic_correction_enabled, snapshot.type);
}
};
template <>
struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint>
: fmt::formatter<fmt::string_view> {
template <typename FormatContext>
auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
FormatContext& ctx) const {
return fmt::format_to(ctx.out(),
"rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}",
time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
time_point.lower, time_point.upper);
}
};

View File

@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/power_state_service.h"
namespace Service::PSC::Time {
@@ -11,39 +12,34 @@ IPowerStateRequestHandler::IPowerStateRequestHandler(
power_state_request_manager} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"},
{1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"},
{0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"},
{1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"},
};
// clang-format on
RegisterHandlers(functions);
}
void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) {
Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent());
*out_event = &m_power_state_request_manager.GetReadableEvent();
R_SUCCEED();
}
void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) {
Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared,
Out<u32> out_priority) {
LOG_DEBUG(Service_Time, "called.");
u32 priority{};
auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority);
*out_cleared = cleared;
if (cleared) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(priority);
rb.Push(cleared);
return;
*out_priority = priority;
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(cleared);
R_SUCCEED();
}
} // namespace Service::PSC::Time

View File

@@ -3,6 +3,7 @@
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/power_state_request_manager.h"
#include "core/hle/service/server_manager.h"
@@ -21,10 +22,10 @@ public:
~IPowerStateRequestHandler() override = default;
private:
void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx);
void GetAndClearPowerStateRequest(HLERequestContext& ctx);
Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority);
private:
Core::System& m_system;
PowerStateRequestManager& m_power_state_request_manager;
};

View File

@@ -3,6 +3,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/power_state_service.h"
#include "core/hle/service/psc/time/service_manager.h"
#include "core/hle/service/psc/time/static.h"
@@ -25,24 +26,24 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"},
{5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"},
{6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"},
{9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"},
{10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"},
{11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"},
{12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"},
{13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"},
{14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"},
{15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"},
{50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"},
{51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"},
{52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"},
{60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
{100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"},
{200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"},
{201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"},
{202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "},
{0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"},
{5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"},
{6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"},
{9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"},
{10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"},
{11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"},
{12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"},
{13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"},
{14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"},
{15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"},
{50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"},
{51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"},
{52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"},
{60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
{100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"},
{200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"},
{201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"},
{202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "},
};
// clang-format on
RegisterHandlers(functions);
@@ -52,302 +53,39 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
m_ephemeral_system_context_writer.Link(m_ephemeral_operation);
}
void ServiceManager::SetupSAndP() {
if (!m_is_s_and_p_setup) {
m_is_s_and_p_setup = true;
m_server_manager.RegisterNamedService(
"time:s", std::make_shared<StaticService>(
m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
m_server_manager.RegisterNamedService("time:p",
std::make_shared<IPowerStateRequestHandler>(
m_system, m_time->m_power_state_request_manager));
}
}
void ServiceManager::CheckAndSetupServicesSAndP() {
if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
SetupSAndP();
}
}
void ServiceManager::Handle_GetStaticServiceAsUser(HLERequestContext& ctx) {
Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<StaticService> service{};
auto res = GetStaticServiceAsUser(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<StaticService>(std::move(service));
}
void ServiceManager::Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<StaticService> service{};
auto res = GetStaticServiceAsAdmin(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<StaticService>(std::move(service));
}
void ServiceManager::Handle_GetStaticServiceAsRepair(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<StaticService> service{};
auto res = GetStaticServiceAsRepair(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<StaticService>(std::move(service));
}
void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<StaticService> service{};
auto res = GetStaticServiceAsServiceManager(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<StaticService>(std::move(service));
}
void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
struct Parameters {
bool reset_detected;
Common::UUID clock_source_id;
s64 rtc_offset;
s64 internal_offset;
s64 test_offset;
};
static_assert(sizeof(Parameters) == 0x30);
IPC::RequestParser rp{ctx};
auto params{rp.PopRaw<Parameters>()};
auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset,
params.internal_offset, params.test_offset,
params.reset_detected);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto context{rp.PopRaw<SystemClockContext>()};
auto time{rp.Pop<s64>()};
auto res = SetupStandardLocalSystemClockCore(context, time);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto context{rp.PopRaw<SystemClockContext>()};
auto accuracy{rp.Pop<s64>()};
auto res = SetupStandardNetworkSystemClockCore(context, accuracy);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
struct Parameters {
bool automatic_correction;
SteadyClockTimePoint time_point;
};
static_assert(sizeof(Parameters) == 0x20);
IPC::RequestParser rp{ctx};
auto params{rp.PopRaw<Parameters>()};
auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
struct Parameters {
u32 location_count;
LocationName name;
SteadyClockTimePoint time_point;
RuleVersion rule_version;
};
static_assert(sizeof(Parameters) == 0x50);
IPC::RequestParser rp{ctx};
auto params{rp.PopRaw<Parameters>()};
auto rule_buffer{ctx.ReadBuffer()};
auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version,
params.location_count, rule_buffer);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
auto res = SetupEphemeralNetworkSystemClockCore();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetStandardLocalClockOperationEvent(&event);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(event->GetReadableEvent());
}
void ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetStandardNetworkClockOperationEventForServiceManager(&event);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(event);
}
void ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetEphemeralNetworkClockOperationEventForServiceManager(&event);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(event);
}
void ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(&event);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(event);
}
void ServiceManager::Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto base_time{rp.Pop<s64>()};
auto res = SetStandardSteadyClockBaseTime(base_time);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetClosestAlarmUpdatedEvent(&event);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.PushCopyObjects(event->GetReadableEvent());
}
void ServiceManager::Handle_CheckAndSignalAlarms(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
auto res = CheckAndSignalAlarms();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
AlarmInfo alarm_info{};
bool is_valid{};
s64 time{};
auto res = GetClosestAlarmInfo(is_valid, alarm_info, time);
struct OutParameters {
bool is_valid;
AlarmInfo alarm_info;
s64 time;
};
static_assert(sizeof(OutParameters) == 0x20);
OutParameters out_params{
.is_valid = is_valid,
.alarm_info = alarm_info,
.time = time,
};
IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<OutParameters>(out_params);
}
// =============================== Implementations ===========================
Result ServiceManager::GetStaticService(std::shared_ptr<StaticService>& out_service,
StaticServiceSetupInfo setup_info, const char* name) {
out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
R_SUCCEED();
}
Result ServiceManager::GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service) {
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u"));
}
Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) {
Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a"));
}
Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) {
Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r"));
}
Result ServiceManager::GetStaticServiceAsServiceManager(
std::shared_ptr<StaticService>& out_service) {
Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm"));
}
Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
s64 internal_offset, s64 test_offset,
bool is_rtc_reset_detected) {
Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected,
Common::UUID& clock_source_id, s64 rtc_offset,
s64 internal_offset, s64 test_offset) {
LOG_DEBUG(Service_Time,
"called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} "
"internal_offset={} test_offset={}",
is_rtc_reset_detected, clock_source_id.RawString(), rtc_offset, internal_offset,
test_offset);
m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset,
is_rtc_reset_detected);
auto time = m_steady_clock.GetRawTime();
@@ -365,6 +103,10 @@ Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_i
}
Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) {
LOG_DEBUG(Service_Time,
"called. context={} context.steady_time_point.clock_source_id={} time={}", context,
context.steady_time_point.clock_source_id.RawString(), time);
m_local_system_clock.SetContextWriter(m_local_system_context_writer);
m_local_system_clock.Initialize(context, time);
@@ -374,6 +116,9 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con
Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context,
s64 accuracy) {
LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}",
context, context.steady_time_point.clock_source_id.RawString(), accuracy);
// TODO this is a hack! The network clock should be updated independently, from the ntc service
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
// to avoid it being stuck at 0.
@@ -388,8 +133,11 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
R_SUCCEED();
}
Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
bool automatic_correction) {
Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction,
SteadyClockTimePoint& time_point) {
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
automatic_correction, time_point, time_point.clock_source_id.RawString());
// TODO this is a hack! The user clock should be updated independently, from the ntc service
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
// to avoid it being stuck at 0.
@@ -406,10 +154,16 @@ Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& ti
R_SUCCEED();
}
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
u32 location_count,
SteadyClockTimePoint& time_point,
RuleVersion& rule_version, u32 location_count,
std::span<const u8> rule_buffer) {
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) {
LOG_DEBUG(Service_Time,
"called. name={} rule_version={} location_count={} time_point={} "
"clock_source_id={}",
name, rule_version, location_count, time_point,
time_point.clock_source_id.RawString());
if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) {
LOG_ERROR(Service_Time, "Failed to parse time zone binary!");
}
@@ -424,6 +178,8 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
}
Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
LOG_DEBUG(Service_Time, "called.");
m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer);
m_ephemeral_network_clock.SetInitialized();
@@ -431,30 +187,41 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
R_SUCCEED();
}
Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) {
*out_event = m_local_operation.m_event;
Result ServiceManager::GetStandardLocalClockOperationEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_local_operation.m_event->GetReadableEvent();
R_SUCCEED();
}
Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager(
Kernel::KEvent** out_event) {
*out_event = m_network_operation.m_event;
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_network_operation.m_event->GetReadableEvent();
R_SUCCEED();
}
Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager(
Kernel::KEvent** out_event) {
*out_event = m_ephemeral_operation.m_event;
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_ephemeral_operation.m_event->GetReadableEvent();
R_SUCCEED();
}
Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
Kernel::KEvent** out_event) {
*out_event = &m_user_system_clock.GetEvent();
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_user_system_clock.GetEvent().GetReadableEvent();
R_SUCCEED();
}
Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
LOG_DEBUG(Service_Time, "called. base_time={}", base_time);
m_steady_clock.SetRtcOffset(base_time);
auto time = m_steady_clock.GetRawTime();
auto ticks = m_system.CoreTiming().GetClockTicks();
@@ -468,26 +235,63 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
R_SUCCEED();
}
Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) {
*out_event = &m_alarms.GetEvent();
Result ServiceManager::GetClosestAlarmUpdatedEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
*out_event = &m_alarms.GetEvent().GetReadableEvent();
R_SUCCEED();
}
Result ServiceManager::CheckAndSignalAlarms() {
LOG_DEBUG(Service_Time, "called.");
m_alarms.CheckAndSignal();
R_SUCCEED();
}
Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) {
Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info,
Out<s64> out_time) {
Alarm* alarm{nullptr};
out_is_valid = m_alarms.GetClosestAlarm(&alarm);
if (out_is_valid) {
out_info = {
*out_is_valid = m_alarms.GetClosestAlarm(&alarm);
if (*out_is_valid) {
*out_info = {
.alert_time = alarm->GetAlertTime(),
.priority = alarm->GetPriority(),
};
out_time = m_alarms.GetRawTime();
*out_time = m_alarms.GetRawTime();
}
LOG_DEBUG(Service_Time,
"called. out_is_valid={} out_info.alert_time={} out_info.priority={}, out_time={}",
*out_is_valid, out_info->alert_time, out_info->priority, *out_time);
R_SUCCEED();
}
void ServiceManager::CheckAndSetupServicesSAndP() {
if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
SetupSAndP();
}
}
void ServiceManager::SetupSAndP() {
if (!m_is_s_and_p_setup) {
m_is_s_and_p_setup = true;
m_server_manager.RegisterNamedService(
"time:s", std::make_shared<StaticService>(
m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
m_server_manager.RegisterNamedService("time:p",
std::make_shared<IPowerStateRequestHandler>(
m_system, m_time->m_power_state_request_manager));
}
}
Result ServiceManager::GetStaticService(OutInterface<StaticService> out_service,
StaticServiceSetupInfo setup_info, const char* name) {
*out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
R_SUCCEED();
}

View File

@@ -6,6 +6,7 @@
#include <list>
#include <memory>
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h"
@@ -29,55 +30,38 @@ public:
ServerManager* server_manager);
~ServiceManager() override = default;
Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service);
Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service);
Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service);
Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service);
Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
s64 internal_offset, s64 test_offset,
bool is_rtc_reset_detected);
Result GetStaticServiceAsUser(OutInterface<StaticService> out_service);
Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service);
Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service);
Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service);
Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id,
s64 rtc_offset, s64 internal_offset, s64 test_offset);
Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time);
Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy);
Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
bool automatic_correction);
Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point,
RuleVersion& rule_version, u32 location_count,
std::span<const u8> rule_buffer);
Result SetupStandardUserSystemClockCore(bool automatic_correction,
SteadyClockTimePoint& time_point);
Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
u32 location_count, SteadyClockTimePoint& time_point,
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer);
Result SetupEphemeralNetworkSystemClockCore();
Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event);
Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event);
Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStandardNetworkClockOperationEventForServiceManager(
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetEphemeralNetworkClockOperationEventForServiceManager(
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result SetStandardSteadyClockBaseTime(s64 base_time);
Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event);
Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result CheckAndSignalAlarms();
Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time);
Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time);
private:
void CheckAndSetupServicesSAndP();
void SetupSAndP();
Result GetStaticService(std::shared_ptr<StaticService>& out_service,
Result GetStaticService(OutInterface<StaticService> out_service,
StaticServiceSetupInfo setup_info, const char* name);
void Handle_GetStaticServiceAsUser(HLERequestContext& ctx);
void Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx);
void Handle_GetStaticServiceAsRepair(HLERequestContext& ctx);
void Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx);
void Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx);
void Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx);
void Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx);
void Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx);
void Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx);
void Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx);
void Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx);
void Handle_GetStandardNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
void Handle_GetEphemeralNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(HLERequestContext& ctx);
void Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx);
void Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx);
void Handle_CheckAndSignalAlarms(HLERequestContext& ctx);
void Handle_GetClosestAlarmInfo(HLERequestContext& ctx);
Core::System& m_system;
std::shared_ptr<TimeManager> m_time;
ServerManager& m_server_manager;

View File

@@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h"
#include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h"
#include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h"
@@ -39,358 +41,122 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup
m_time->m_shared_memory} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
{1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
{2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
{3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
{4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
{5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
{20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
{50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
{51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
{100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
{200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
{401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
{500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
};
// clang-format on
RegisterHandlers(functions);
}
Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot,
SystemClockContext& user_context,
SystemClockContext& network_context, TimeType type) {
out_snapshot.user_context = user_context;
out_snapshot.network_context = network_context;
Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
R_TRY(
m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point));
out_snapshot.is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
R_TRY(m_time_zone.GetLocationName(out_snapshot.location_name));
R_TRY(GetTimeFromTimePointAndContext(
&out_snapshot.user_time, out_snapshot.steady_clock_time_point, out_snapshot.user_context));
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.user_calendar_time,
out_snapshot.user_calendar_additional_time,
out_snapshot.user_time));
if (GetTimeFromTimePointAndContext(&out_snapshot.network_time,
out_snapshot.steady_clock_time_point,
out_snapshot.network_context) != ResultSuccess) {
out_snapshot.network_time = 0;
}
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.network_calendar_time,
out_snapshot.network_calendar_additional_time,
out_snapshot.network_time));
out_snapshot.type = type;
out_snapshot.unk_CE = 0;
*out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
m_setup_info.can_write_user_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED();
}
void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<SystemClock> service{};
auto res = GetStandardUserSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<SystemClock>(std::move(service));
}
void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<SystemClock> service{};
auto res = GetStandardNetworkSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<SystemClock>(std::move(service));
}
void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<SteadyClock> service{};
auto res = GetStandardSteadyClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface(std::move(service));
}
void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<TimeZoneService> service{};
auto res = GetTimeZoneService(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface(std::move(service));
}
void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<SystemClock> service{};
auto res = GetStandardLocalSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<SystemClock>(std::move(service));
}
void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
std::shared_ptr<SystemClock> service{};
auto res = GetEphemeralNetworkSystemClock(service);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res);
rb.PushIpcInterface<SystemClock>(std::move(service));
}
void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KSharedMemory* shared_memory{};
auto res = GetSharedMemoryNativeHandle(&shared_memory);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(shared_memory);
}
void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(m_setup_info.can_write_steady_clock ? ResultNotImplemented : ResultPermissionDenied);
}
void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
}
void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
bool is_enabled{};
auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push<bool>(is_enabled);
}
void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto automatic_correction{rp.Pop<bool>()};
auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
}
void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
bool is_sufficient{};
auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push<bool>(is_sufficient);
}
void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
SteadyClockTimePoint time_point{};
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<SteadyClockTimePoint>(time_point);
}
void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto context{rp.PopRaw<SystemClockContext>()};
s64 time{};
auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push<s64>(time);
}
void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto type{rp.PopEnum<TimeType>()};
ClockSnapshot snapshot{};
auto res = GetClockSnapshot(snapshot, type);
ctx.WriteBuffer(snapshot);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto clock_type{rp.PopEnum<TimeType>()};
[[maybe_unused]] auto alignment{rp.Pop<u32>()};
auto user_context{rp.PopRaw<SystemClockContext>()};
auto network_context{rp.PopRaw<SystemClockContext>()};
ClockSnapshot snapshot{};
auto res =
GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
ctx.WriteBuffer(snapshot);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
ClockSnapshot a{};
ClockSnapshot b{};
auto a_buffer{ctx.ReadBuffer(0)};
auto b_buffer{ctx.ReadBuffer(1)};
std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
s64 difference{};
auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(difference);
}
void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
ClockSnapshot a{};
ClockSnapshot b{};
auto a_buffer{ctx.ReadBuffer(0)};
auto b_buffer{ctx.ReadBuffer(1)};
std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
s64 time{};
auto res = CalculateSpanBetween(time, a, b);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(time);
}
// =============================== Implementations ===========================
Result StaticService::GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service) {
out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
m_setup_info.can_write_user_clock,
m_setup_info.can_write_uninitialized_clock);
*out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
m_setup_info.can_write_network_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED();
}
Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
m_setup_info.can_write_network_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED();
}
Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) {
out_service =
*out_service =
std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED();
}
Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
out_service =
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
LOG_DEBUG(Service_Time, "called.");
*out_service =
std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone,
m_setup_info.can_write_timezone_device_location);
R_SUCCEED();
}
Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service) {
out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
m_setup_info.can_write_local_clock,
m_setup_info.can_write_uninitialized_clock);
Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
*out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
m_setup_info.can_write_local_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED();
}
Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
m_setup_info.can_write_network_clock,
m_setup_info.can_write_uninitialized_clock);
Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) {
LOG_DEBUG(Service_Time, "called.");
*out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
m_setup_info.can_write_network_clock,
m_setup_info.can_write_uninitialized_clock);
R_SUCCEED();
}
Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
Result StaticService::GetSharedMemoryNativeHandle(
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
LOG_DEBUG(Service_Time, "called.");
*out_shared_memory = &m_shared_memory.GetKSharedMemory();
R_SUCCEED();
}
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) {
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
R_UNLESS(m_setup_info.can_write_steady_clock, ResultPermissionDenied);
R_RETURN(ResultNotImplemented);
}
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
R_RETURN(ResultNotImplemented);
}
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
Out<bool> out_is_enabled) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); });
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
*out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
R_SUCCEED();
}
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
bool automatic_correction) {
LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(),
ResultClockUninitialized);
R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied);
@@ -407,22 +173,35 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
R_SUCCEED();
}
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) {
out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
R_RETURN(ResultNotImplemented);
}
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
*out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
R_SUCCEED();
}
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
SteadyClockTimePoint& out_time_point) {
Out<SteadyClockTimePoint> out_time_point) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
m_user_system_clock.GetTimePoint(out_time_point);
m_user_system_clock.GetTimePoint(*out_time_point);
R_SUCCEED();
}
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
SystemClockContext& context) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized);
SteadyClockTimePoint time_point{};
@@ -433,12 +212,16 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
auto one_second_ns{
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
auto ticks{m_system.CoreTiming().GetClockTicks()};
auto current_time{ConvertToTimeSpan(ticks).count()};
out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns));
auto current_time_ns{ConvertToTimeSpan(ticks).count()};
*out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns));
R_SUCCEED();
}
Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) {
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) {
SCOPE_EXIT(
{ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
SystemClockContext user_context{};
R_TRY(m_user_system_clock.GetContext(user_context));
@@ -448,53 +231,101 @@ Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType typ
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
}
Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type,
OutClockSnapshot out_snapshot,
SystemClockContext& user_context,
SystemClockContext& network_context,
TimeType type) {
SystemClockContext& network_context) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time,
"called. type={} user_context={} network_context={} out_snapshot={}", type,
user_context, network_context, *out_snapshot);
});
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
}
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
ClockSnapshot& a,
ClockSnapshot& b) {
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
InClockSnapshot a,
InClockSnapshot b) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference);
});
auto diff_s =
std::chrono::seconds(b.user_context.offset) - std::chrono::seconds(a.user_context.offset);
std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset);
if (a.user_context == b.user_context ||
!a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) {
out_time = 0;
if (a->user_context == b->user_context ||
!a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) {
*out_difference = 0;
R_SUCCEED();
}
if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) {
out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) {
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
R_SUCCEED();
}
if (a.network_context.steady_time_point.IdMatches(a.steady_clock_time_point) ||
b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) {
out_time = 0;
if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) ||
b->network_context.steady_time_point.IdMatches(b->steady_clock_time_point)) {
*out_difference = 0;
R_SUCCEED();
}
out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
R_SUCCEED();
}
Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) {
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
InClockSnapshot b) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
s64 time_s{};
auto res =
GetSpanBetweenTimePoints(&time_s, a.steady_clock_time_point, b.steady_clock_time_point);
GetSpanBetweenTimePoints(&time_s, a->steady_clock_time_point, b->steady_clock_time_point);
if (res != ResultSuccess) {
R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound);
time_s = b.network_time - a.network_time;
R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound);
time_s = b->network_time - a->network_time;
}
out_time =
*out_time =
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count();
R_SUCCEED();
}
Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot,
SystemClockContext& user_context,
SystemClockContext& network_context, TimeType type) {
out_snapshot->user_context = user_context;
out_snapshot->network_context = network_context;
R_TRY(
m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot->steady_clock_time_point));
out_snapshot->is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
R_TRY(m_time_zone.GetLocationName(out_snapshot->location_name));
R_TRY(GetTimeFromTimePointAndContext(&out_snapshot->user_time,
out_snapshot->steady_clock_time_point,
out_snapshot->user_context));
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->user_calendar_time,
out_snapshot->user_calendar_additional_time,
out_snapshot->user_time));
if (GetTimeFromTimePointAndContext(&out_snapshot->network_time,
out_snapshot->steady_clock_time_point,
out_snapshot->network_context) != ResultSuccess) {
out_snapshot->network_time = 0;
}
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->network_calendar_time,
out_snapshot->network_calendar_additional_time,
out_snapshot->network_time));
out_snapshot->type = type;
out_snapshot->unk_CE = 0;
R_SUCCEED();
}
} // namespace Service::PSC::Time

View File

@@ -3,6 +3,7 @@
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/server_manager.h"
@@ -29,58 +30,44 @@ class EphemeralNetworkSystemClockCore;
class SharedMemory;
class StaticService final : public ServiceFramework<StaticService> {
using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
public:
explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info,
std::shared_ptr<TimeManager> time, const char* name);
~StaticService() override = default;
Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service);
Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled);
Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service);
Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service);
Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service);
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service);
Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service);
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
SteadyClockTimePoint& out_time_point);
Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context);
Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type);
Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
Out<SteadyClockTimePoint> out_time_point);
Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
SystemClockContext& context);
Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type);
Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot,
SystemClockContext& user_context,
SystemClockContext& network_context,
TimeType type);
Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a,
ClockSnapshot& b);
Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b);
SystemClockContext& network_context);
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
InClockSnapshot a, InClockSnapshot b);
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
private:
Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context,
Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context,
SystemClockContext& network_context, TimeType type);
void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
void Handle_GetTimeZoneService(HLERequestContext& ctx);
void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
void Handle_GetClockSnapshot(HLERequestContext& ctx);
void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
void Handle_CalculateSpanBetween(HLERequestContext& ctx);
Core::System& m_system;
StaticServiceSetupInfo m_setup_info;
std::shared_ptr<TimeManager> m_time;

View File

@@ -1,7 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/steady_clock.h"
namespace Service::PSC::Time {
@@ -14,114 +16,40 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
can_write_uninitialized_clock} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"},
{2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"},
{3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"},
{100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"},
{101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"},
{102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"},
{200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"},
{0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"},
{2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"},
{3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"},
{100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"},
{101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"},
{102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"},
{200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"},
};
// clang-format on
RegisterHandlers(functions);
}
void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
SteadyClockTimePoint time_point{};
auto res = GetCurrentTimePoint(time_point);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<SteadyClockTimePoint>(time_point);
}
void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
s64 test_offset{};
auto res = GetTestOffset(test_offset);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(test_offset);
}
void SteadyClock::Handle_SetTestOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto test_offset{rp.Pop<s64>()};
auto res = SetTestOffset(test_offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void SteadyClock::Handle_GetRtcValue(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
s64 rtc_value{};
auto res = GetRtcValue(rtc_value);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(rtc_value);
}
void SteadyClock::Handle_IsRtcResetDetected(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
bool reset_detected{false};
auto res = IsRtcResetDetected(reset_detected);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(reset_detected);
}
void SteadyClock::Handle_GetSetupResultValue(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result result_value{ResultSuccess};
auto res = GetSetupResultValue(result_value);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(result_value);
}
void SteadyClock::Handle_GetInternalOffset(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
s64 internal_offset{};
auto res = GetInternalOffset(internal_offset);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push(internal_offset);
}
// =============================== Implementations ===========================
Result SteadyClock::GetCurrentTimePoint(SteadyClockTimePoint& out_time_point) {
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point));
R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point));
}
Result SteadyClock::GetTestOffset(s64& out_test_offset) {
Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); });
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
out_test_offset = m_clock_core.GetTestOffset();
*out_test_offset = m_clock_core.GetTestOffset();
R_SUCCEED();
}
Result SteadyClock::SetTestOffset(s64 test_offset) {
LOG_DEBUG(Service_Time, "called. test_offset={}", test_offset);
R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied);
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -130,34 +58,43 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {
R_SUCCEED();
}
Result SteadyClock::GetRtcValue(s64& out_rtc_value) {
Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
R_RETURN(m_clock_core.GetRtcValue(out_rtc_value));
R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value));
}
Result SteadyClock::IsRtcResetDetected(bool& out_is_detected) {
Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); });
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
out_is_detected = m_clock_core.IsResetDetected();
*out_is_detected = m_clock_core.IsResetDetected();
R_SUCCEED();
}
Result SteadyClock::GetSetupResultValue(Result& out_result) {
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); });
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
out_result = m_clock_core.GetSetupResultValue();
*out_result = m_clock_core.GetSetupResultValue();
R_SUCCEED();
}
Result SteadyClock::GetInternalOffset(s64& out_internal_offset) {
Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) {
SCOPE_EXIT(
{ LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); });
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
out_internal_offset = m_clock_core.GetInternalOffset();
*out_internal_offset = m_clock_core.GetInternalOffset();
R_SUCCEED();
}

View File

@@ -3,6 +3,7 @@
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h"
@@ -22,23 +23,15 @@ public:
~SteadyClock() override = default;
Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point);
Result GetTestOffset(s64& out_test_offset);
Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point);
Result GetTestOffset(Out<s64> out_test_offset);
Result SetTestOffset(s64 test_offset);
Result GetRtcValue(s64& out_rtc_value);
Result IsRtcResetDetected(bool& out_is_detected);
Result GetSetupResultValue(Result& out_result);
Result GetInternalOffset(s64& out_internal_offset);
Result GetRtcValue(Out<s64> out_rtc_value);
Result IsRtcResetDetected(Out<bool> out_is_detected);
Result GetSetupResultValue(Out<Result> out_result);
Result GetInternalOffset(Out<s64> out_internal_offset);
private:
void Handle_GetCurrentTimePoint(HLERequestContext& ctx);
void Handle_GetTestOffset(HLERequestContext& ctx);
void Handle_SetTestOffset(HLERequestContext& ctx);
void Handle_GetRtcValue(HLERequestContext& ctx);
void Handle_IsRtcResetDetected(HLERequestContext& ctx);
void Handle_GetSetupResultValue(HLERequestContext& ctx);
void Handle_GetInternalOffset(HLERequestContext& ctx);
Core::System& m_system;
StandardSteadyClockCore& m_clock_core;

View File

@@ -1,7 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/system_clock.h"
namespace Service::PSC::Time {
@@ -13,83 +15,28 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo
can_write_uninitialized_clock} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"},
{1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"},
{2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"},
{3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"},
{4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"},
{0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"},
{1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"},
{2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"},
{3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"},
{4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"},
};
// clang-format on
RegisterHandlers(functions);
}
void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result SystemClock::GetCurrentTime(Out<s64> out_time) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); });
s64 time{};
auto res = GetCurrentTime(time);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res);
rb.Push<s64>(time);
}
void SystemClock::Handle_SetCurrentTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto time{rp.Pop<s64>()};
auto res = SetCurrentTime(time);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void SystemClock::Handle_GetSystemClockContext(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
SystemClockContext context{};
auto res = GetSystemClockContext(context);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SystemClockContext) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<SystemClockContext>(context);
}
void SystemClock::Handle_SetSystemClockContext(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto context{rp.PopRaw<SystemClockContext>()};
auto res = SetSystemClockContext(context);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void SystemClock::Handle_GetOperationEventReadableHandle(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Kernel::KEvent* event{};
auto res = GetOperationEventReadableHandle(&event);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(res);
rb.PushCopyObjects(event->GetReadableEvent());
}
// =============================== Implementations ===========================
Result SystemClock::GetCurrentTime(s64& out_time) {
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
R_RETURN(m_clock_core.GetCurrentTime(&out_time));
R_RETURN(m_clock_core.GetCurrentTime(out_time.Get()));
}
Result SystemClock::SetCurrentTime(s64 time) {
LOG_DEBUG(Service_Time, "called. time={}", time);
R_UNLESS(m_can_write_clock, ResultPermissionDenied);
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -97,14 +44,18 @@ Result SystemClock::SetCurrentTime(s64 time) {
R_RETURN(m_clock_core.SetCurrentTime(time));
}
Result SystemClock::GetSystemClockContext(SystemClockContext& out_context) {
Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); });
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
R_RETURN(m_clock_core.GetContext(out_context));
R_RETURN(m_clock_core.GetContext(*out_context));
}
Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
LOG_DEBUG(Service_Time, "called. context={}", context);
R_UNLESS(m_can_write_clock, ResultPermissionDenied);
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
ResultClockUninitialized);
@@ -112,7 +63,10 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
R_RETURN(m_clock_core.SetContextAndWrite(context));
}
Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) {
Result SystemClock::GetOperationEventReadableHandle(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called.");
if (!m_operation_event) {
m_operation_event = std::make_unique<OperationEvent>(m_system);
R_UNLESS(m_operation_event != nullptr, ResultFailed);
@@ -120,7 +74,7 @@ Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event)
m_clock_core.LinkOperationEvent(*m_operation_event);
}
*out_event = m_operation_event->m_event;
*out_event = &m_operation_event->m_event->GetReadableEvent();
R_SUCCEED();
}

View File

@@ -3,6 +3,7 @@
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h"
@@ -22,19 +23,13 @@ public:
~SystemClock() override = default;
Result GetCurrentTime(s64& out_time);
Result GetCurrentTime(Out<s64> out_time);
Result SetCurrentTime(s64 time);
Result GetSystemClockContext(SystemClockContext& out_context);
Result GetSystemClockContext(Out<SystemClockContext> out_context);
Result SetSystemClockContext(SystemClockContext& context);
Result GetOperationEventReadableHandle(Kernel::KEvent** out_event);
Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
private:
void Handle_GetCurrentTime(HLERequestContext& ctx);
void Handle_SetCurrentTime(HLERequestContext& ctx);
void Handle_GetSystemClockContext(HLERequestContext& ctx);
void Handle_SetSystemClockContext(HLERequestContext& ctx);
void Handle_GetOperationEventReadableHandle(HLERequestContext& ctx);
Core::System& m_system;
SystemClockCore& m_clock_core;

View File

@@ -5,7 +5,7 @@
namespace Service::PSC::Time {
namespace {
constexpr Result ValidateRule(Tz::Rule& rule) {
constexpr Result ValidateRule(const Tz::Rule& rule) {
if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) ||
rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) ||
rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) {
@@ -26,7 +26,7 @@ constexpr Result ValidateRule(Tz::Rule& rule) {
R_SUCCEED();
}
constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index,
constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index,
s32 index_offset) {
s32 found_idx{};
s32 expected_index{index + index_offset};
@@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) {
Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time,
Tz::Rule& rule) {
const Tz::Rule& rule) {
std::scoped_lock l{m_mutex};
R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule));
}
@@ -140,8 +140,8 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary)
R_RETURN(ParseBinaryImpl(out_rule, binary));
}
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
CalendarTime& calendar, Tz::Rule& rule) {
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
CalendarTime& calendar, const Tz::Rule& rule) {
std::scoped_lock l{m_mutex};
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
@@ -157,7 +157,7 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 ou
R_RETURN(res);
}
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
u32 out_times_count, CalendarTime& calendar) {
std::scoped_lock l{m_mutex};
@@ -183,7 +183,7 @@ Result TimeZone::ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary)
Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time,
Tz::Rule& rule) {
const Tz::Rule& rule) {
R_TRY(ValidateRule(rule));
Tz::CalendarTimeInternal calendar_internal{};
@@ -212,8 +212,8 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
R_SUCCEED();
}
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) {
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) {
R_TRY(ValidateRule(rule));
calendar.month -= 1;

View File

@@ -32,23 +32,24 @@ public:
Result GetTimePoint(SteadyClockTimePoint& out_time_point);
Result ToCalendarTime(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
CalendarAdditionalInfo& out_additional_info, s64 time,
const Tz::Rule& rule);
Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time,
CalendarAdditionalInfo& calendar_additional, s64 time);
Result ParseBinary(LocationName& name, std::span<const u8> binary);
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
CalendarTime& calendar, Tz::Rule& rule);
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
CalendarTime& calendar, const Tz::Rule& rule);
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count,
CalendarTime& calendar);
private:
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time,
Tz::Rule& rule);
Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
CalendarTime& calendar, Tz::Rule& rule, s32 is_dst);
const Tz::Rule& rule);
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
bool m_initialized{};
std::recursive_mutex m_mutex;

View File

@@ -2,7 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <tz/tz.h>
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/time/time_zone_service.h"
namespace Service::PSC::Time {
@@ -14,240 +17,78 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&
can_write_timezone_device_location} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
{1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
{2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
{3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
{4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
{5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
{6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
{7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
{8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
{20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
{101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
{201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
{202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
};
// clang-format on
RegisterHandlers(functions);
}
void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
LocationName name{};
auto res = GetDeviceLocationName(name);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(LocationName) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<LocationName>(name);
R_RETURN(m_time_zone.GetLocationName(*out_location_name));
}
void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
IPC::RequestParser rp{ctx};
[[maybe_unused]] auto name{rp.PopRaw<LocationName>()};
if (!m_can_write_timezone_device_location) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultPermissionDenied);
return;
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
R_RETURN(ResultNotImplemented);
}
void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
u32 count{};
auto res = GetTotalLocationNameCount(count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
R_RETURN(m_time_zone.GetTotalLocationCount(*out_count));
}
void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::LoadLocationNameList(
Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
R_RETURN(ResultNotImplemented);
}
void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
R_RETURN(ResultNotImplemented);
}
void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
RuleVersion rule_version{};
auto res = GetTimeZoneRuleVersion(rule_version);
IPC::ResponseBuilder rb{ctx, 2 + sizeof(RuleVersion) / sizeof(u32)};
rb.Push(res);
rb.PushRaw<RuleVersion>(rule_version);
R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version));
}
void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",
*out_location_name, *out_time_point);
});
LocationName name{};
SteadyClockTimePoint time_point{};
auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(LocationName) / sizeof(u32)) +
(sizeof(SteadyClockTimePoint) / sizeof(u32))};
rb.Push(res);
rb.PushRaw<LocationName>(name);
rb.PushRaw<SteadyClockTimePoint>(time_point);
R_TRY(m_time_zone.GetLocationName(*out_location_name));
R_RETURN(m_time_zone.GetTimePoint(*out_time_point));
}
void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
IPC::RequestParser rp{ctx};
auto name{rp.PopRaw<LocationName>()};
auto binary{ctx.ReadBuffer()};
auto res = SetDeviceLocationNameWithTimeZoneRule(name, binary);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
auto binary{ctx.ReadBuffer()};
Tz::Rule rule{};
auto res = ParseTimeZoneBinary(rule, binary);
ctx.WriteBuffer(rule);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
}
void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle(
HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultNotImplemented);
}
void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto time{rp.Pop<s64>()};
auto rule_buffer{ctx.ReadBuffer()};
Tz::Rule rule{};
std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
CalendarTime calendar_time{};
CalendarAdditionalInfo additional_info{};
auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
(sizeof(CalendarAdditionalInfo) / sizeof(u32))};
rb.Push(res);
rb.PushRaw<CalendarTime>(calendar_time);
rb.PushRaw<CalendarAdditionalInfo>(additional_info);
}
void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto time{rp.Pop<s64>()};
CalendarTime calendar_time{};
CalendarAdditionalInfo additional_info{};
auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
(sizeof(CalendarAdditionalInfo) / sizeof(u32))};
rb.Push(res);
rb.PushRaw<CalendarTime>(calendar_time);
rb.PushRaw<CalendarAdditionalInfo>(additional_info);
}
void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto calendar{rp.PopRaw<CalendarTime>()};
auto binary{ctx.ReadBuffer()};
Tz::Rule rule{};
std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
u32 count{};
std::array<s64, 2> times{};
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
auto res = ToPosixTime(count, times, times_count, calendar, rule);
ctx.WriteBuffer(times);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
}
void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called.");
IPC::RequestParser rp{ctx};
auto calendar{rp.PopRaw<CalendarTime>()};
u32 count{};
std::array<s64, 2> times{};
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
ctx.WriteBuffer(times);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res);
rb.Push(count);
}
// =============================== Implementations ===========================
Result TimeZoneService::GetDeviceLocationName(LocationName& out_location_name) {
R_RETURN(m_time_zone.GetLocationName(out_location_name));
}
Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) {
R_RETURN(m_time_zone.GetTotalLocationCount(out_count));
}
Result TimeZoneService::GetTimeZoneRuleVersion(RuleVersion& out_rule_version) {
R_RETURN(m_time_zone.GetRuleVersion(out_rule_version));
}
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
LocationName& location_name) {
R_TRY(m_time_zone.GetLocationName(location_name));
R_RETURN(m_time_zone.GetTimePoint(out_time_point));
}
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
std::span<const u8> binary) {
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
R_TRY(m_time_zone.ParseBinary(location_name, binary));
@@ -258,32 +99,71 @@ Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& loca
R_SUCCEED();
}
Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) {
R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary));
Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
InBuffer<BufferAttr_HipcAutoSelect> binary) {
LOG_DEBUG(Service_Time, "called.");
R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary));
}
Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time,
Tz::Rule& rule) {
R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
R_RETURN(ResultNotImplemented);
}
Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info,
s64 time) {
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
}
Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info, s64 time,
InRule rule) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
});
Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
u32 out_times_count, CalendarTime& calendar_time,
Tz::Rule& rule) {
R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
}
Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
u32 out_times_count, CalendarTime& calendar_time) {
R_RETURN(
m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time));
m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get()));
}
Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info,
s64 time) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
*out_calendar_time, *out_additional_info);
});
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time));
}
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count, CalendarTime& calendar_time,
InRule rule) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
"out_times_count={}",
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
});
R_RETURN(
m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule));
}
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count,
CalendarTime& calendar_time) {
SCOPE_EXIT({
LOG_DEBUG(Service_Time,
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
"out_times_count={}",
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
});
R_RETURN(
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time));
}
} // namespace Service::PSC::Time

View File

@@ -3,6 +3,7 @@
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/psc/time/manager.h"
@@ -20,45 +21,41 @@ struct Rule;
namespace Service::PSC::Time {
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
public:
explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core,
TimeZone& time_zone, bool can_write_timezone_device_location);
~TimeZoneService() override = default;
Result GetDeviceLocationName(LocationName& out_location_name);
Result GetTotalLocationNameCount(u32& out_count);
Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version);
Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
LocationName& location_name);
Result GetDeviceLocationName(Out<LocationName> out_location_name);
Result SetDeviceLocationName(LocationName& location_name);
Result GetTotalLocationNameCount(Out<u32> out_count);
Result LoadLocationNameList(Out<u32> out_count,
OutArray<LocationName, BufferAttr_HipcMapAlias> out_names,
u32 index);
Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name);
Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version);
Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name,
Out<SteadyClockTimePoint> out_time_point);
Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
std::span<const u8> binary);
Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary);
Result ToCalendarTime(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
CalendarAdditionalInfo& out_additional_info, s64 time);
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
CalendarTime& calendar_time, Tz::Rule& rule);
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
CalendarTime& calendar_time);
InBuffer<BufferAttr_HipcAutoSelect> binary);
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
Result GetDeviceLocationNameOperationEventReadableHandle(
OutCopyHandle<Kernel::KReadableEvent> out_event);
Result ToCalendarTime(Out<CalendarTime> out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule);
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
Out<CalendarAdditionalInfo> out_additional_info, s64 time);
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule);
Result ToPosixTimeWithMyRule(Out<u32> out_count,
OutArray<s64, BufferAttr_HipcPointer> out_times,
Out<u32> out_times_count, CalendarTime& calendar_time);
private:
void Handle_GetDeviceLocationName(HLERequestContext& ctx);
void Handle_SetDeviceLocationName(HLERequestContext& ctx);
void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
void Handle_LoadLocationNameList(HLERequestContext& ctx);
void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
void Handle_ToCalendarTime(HLERequestContext& ctx);
void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
void Handle_ToPosixTime(HLERequestContext& ctx);
void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
Core::System& m_system;
StandardSteadyClockCore& m_clock_core;

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()) {
@@ -817,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);
@@ -826,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();
@@ -969,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);
@@ -1132,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);
@@ -1141,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.");
@@ -1164,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);
@@ -1173,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);
@@ -1193,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) {
@@ -1300,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";
@@ -1390,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

@@ -7,8 +7,6 @@ add_executable(yuzu-room
yuzu_room.rc
)
create_target_directory_groups(yuzu-room)
target_link_libraries(yuzu-room PRIVATE common network)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE)
@@ -28,3 +26,5 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h)
endif()
create_target_directory_groups(yuzu-room)

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

@@ -289,8 +289,6 @@ add_library(video_core STATIC
vulkan_common/vulkan.h
)
create_target_directory_groups(video_core)
target_link_libraries(video_core PUBLIC common core)
target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder)
@@ -365,3 +363,5 @@ endif()
if (ANDROID AND ARCHITECTURE_arm64)
target_link_libraries(video_core PRIVATE adrenotools)
endif()
create_target_directory_groups(video_core)

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
@@ -375,8 +378,6 @@ elseif(WIN32)
endif()
endif()
create_target_directory_groups(yuzu)
target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
@@ -472,3 +473,5 @@ endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(yuzu PRIVATE precompiled_headers.h)
endif()
create_target_directory_groups(yuzu)

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"));

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