summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/core.cpp22
-rw-r--r--src/core/frontend/emu_window.h44
-rw-r--r--src/core/frontend/scope_acquire_context.cpp18
-rw-r--r--src/core/frontend/scope_acquire_context.h23
-rw-r--r--src/core/hle/service/am/am.cpp42
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/caps/caps.cpp158
-rw-r--r--src/core/hle/service/caps/caps.h71
-rw-r--r--src/core/hle/service/caps/caps_a.cpp78
-rw-r--r--src/core/hle/service/caps/caps_a.h21
-rw-r--r--src/core/hle/service/caps/caps_c.cpp75
-rw-r--r--src/core/hle/service/caps/caps_c.h21
-rw-r--r--src/core/hle/service/caps/caps_sc.cpp40
-rw-r--r--src/core/hle/service/caps/caps_sc.h21
-rw-r--r--src/core/hle/service/caps/caps_ss.cpp26
-rw-r--r--src/core/hle/service/caps/caps_ss.h21
-rw-r--r--src/core/hle/service/caps/caps_su.cpp22
-rw-r--r--src/core/hle/service/caps/caps_su.h21
-rw-r--r--src/core/hle/service/caps/caps_u.cpp76
-rw-r--r--src/core/hle/service/caps/caps_u.h24
-rw-r--r--src/core/hle/service/hid/hid.cpp9
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/core/hle/service/time/interface.cpp2
-rw-r--r--src/core/hle/service/time/time.cpp29
-rw-r--r--src/core/hle/service/time/time.h1
26 files changed, 652 insertions, 231 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b31a0328c..66497a386 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -131,8 +131,6 @@ add_library(core STATIC
frontend/framebuffer_layout.cpp
frontend/framebuffer_layout.h
frontend/input.h
- frontend/scope_acquire_context.cpp
- frontend/scope_acquire_context.h
gdbstub/gdbstub.cpp
gdbstub/gdbstub.h
hardware_interrupt_manager.cpp
@@ -287,6 +285,18 @@ add_library(core STATIC
hle/service/btm/btm.h
hle/service/caps/caps.cpp
hle/service/caps/caps.h
+ hle/service/caps/caps_a.cpp
+ hle/service/caps/caps_a.h
+ hle/service/caps/caps_c.cpp
+ hle/service/caps/caps_c.h
+ hle/service/caps/caps_u.cpp
+ hle/service/caps/caps_u.h
+ hle/service/caps/caps_sc.cpp
+ hle/service/caps/caps_sc.h
+ hle/service/caps/caps_ss.cpp
+ hle/service/caps/caps_ss.h
+ hle/service/caps/caps_su.cpp
+ hle/service/caps/caps_su.h
hle/service/erpt/erpt.cpp
hle/service/erpt/erpt.h
hle/service/es/es.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index d1bc9340d..3bd90d79f 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -24,7 +24,6 @@
#include "core/file_sys/sdmc_factory.h"
#include "core/file_sys/vfs_concat.h"
#include "core/file_sys/vfs_real.h"
-#include "core/frontend/scope_acquire_context.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hardware_interrupt_manager.h"
#include "core/hle/kernel/client_port.h"
@@ -168,13 +167,12 @@ struct System::Impl {
Service::Init(service_manager, system);
GDBStub::DeferStart();
- renderer = VideoCore::CreateRenderer(emu_window, system);
- if (!renderer->Init()) {
+ interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
+ gpu_core = VideoCore::CreateGPU(emu_window, system);
+ if (!gpu_core) {
return ResultStatus::ErrorVideoCore;
}
- interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
- gpu_core = VideoCore::CreateGPU(system);
- renderer->Rasterizer().SetupDirtyFlags();
+ gpu_core->Renderer().Rasterizer().SetupDirtyFlags();
is_powered_on = true;
exit_lock = false;
@@ -186,8 +184,6 @@ struct System::Impl {
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
const std::string& filepath) {
- Core::Frontend::ScopeAcquireContext acquire_context{emu_window};
-
app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
if (!app_loader) {
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
@@ -216,10 +212,6 @@ struct System::Impl {
AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.MakeCurrentProcess(main_process.get());
- // Main process has been loaded and been made current.
- // Begin GPU and CPU execution.
- gpu_core->Start();
-
// Initialize cheat engine
if (cheat_engine) {
cheat_engine->Initialize();
@@ -277,7 +269,6 @@ struct System::Impl {
}
// Shutdown emulation session
- renderer.reset();
GDBStub::Shutdown();
Service::Shutdown();
service_manager.reset();
@@ -353,7 +344,6 @@ struct System::Impl {
Service::FileSystem::FileSystemController fs_controller;
/// AppLoader used to load the current executing application
std::unique_ptr<Loader::AppLoader> app_loader;
- std::unique_ptr<VideoCore::RendererBase> renderer;
std::unique_ptr<Tegra::GPU> gpu_core;
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
Memory::Memory memory;
@@ -536,11 +526,11 @@ const Core::Hardware::InterruptManager& System::InterruptManager() const {
}
VideoCore::RendererBase& System::Renderer() {
- return *impl->renderer;
+ return impl->gpu_core->Renderer();
}
const VideoCore::RendererBase& System::Renderer() const {
- return *impl->renderer;
+ return impl->gpu_core->Renderer();
}
Kernel::KernelCore& System::Kernel() {
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index 5eb87fb63..72294d4d8 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -13,19 +13,39 @@
namespace Core::Frontend {
/**
- * Represents a graphics context that can be used for background computation or drawing. If the
- * graphics backend doesn't require the context, then the implementation of these methods can be
- * stubs
+ * Represents a drawing context that supports graphics operations.
*/
class GraphicsContext {
public:
virtual ~GraphicsContext();
+ /// Inform the driver to swap the front/back buffers and present the current image
+ virtual void SwapBuffers() {}
+
/// Makes the graphics context current for the caller thread
- virtual void MakeCurrent() = 0;
+ virtual void MakeCurrent() {}
/// Releases (dunno if this is the "right" word) the context from the caller thread
- virtual void DoneCurrent() = 0;
+ virtual void DoneCurrent() {}
+
+ class Scoped {
+ public:
+ explicit Scoped(GraphicsContext& context_) : context(context_) {
+ context.MakeCurrent();
+ }
+ ~Scoped() {
+ context.DoneCurrent();
+ }
+
+ private:
+ GraphicsContext& context;
+ };
+
+ /// Calls MakeCurrent on the context and calls DoneCurrent when the scope for the returned value
+ /// ends
+ Scoped Acquire() {
+ return Scoped{*this};
+ }
};
/**
@@ -46,7 +66,7 @@ public:
* - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please
* re-read the upper points again and think about it if you don't see this.
*/
-class EmuWindow : public GraphicsContext {
+class EmuWindow {
public:
/// Data structure to store emuwindow configuration
struct WindowConfig {
@@ -60,17 +80,9 @@ public:
virtual void PollEvents() = 0;
/**
- * Returns a GraphicsContext that the frontend provides that is shared with the emu window. This
- * context can be used from other threads for background graphics computation. If the frontend
- * is using a graphics backend that doesn't need anything specific to run on a different thread,
- * then it can use a stubbed implemenation for GraphicsContext.
- *
- * If the return value is null, then the core should assume that the frontend cannot provide a
- * Shared Context
+ * Returns a GraphicsContext that the frontend provides to be used for rendering.
*/
- virtual std::unique_ptr<GraphicsContext> CreateSharedContext() const {
- return nullptr;
- }
+ virtual std::unique_ptr<GraphicsContext> CreateSharedContext() const = 0;
/// Returns if window is shown (not minimized)
virtual bool IsShown() const = 0;
diff --git a/src/core/frontend/scope_acquire_context.cpp b/src/core/frontend/scope_acquire_context.cpp
deleted file mode 100644
index 878c3157c..000000000
--- a/src/core/frontend/scope_acquire_context.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/frontend/emu_window.h"
-#include "core/frontend/scope_acquire_context.h"
-
-namespace Core::Frontend {
-
-ScopeAcquireContext::ScopeAcquireContext(Core::Frontend::GraphicsContext& context)
- : context{context} {
- context.MakeCurrent();
-}
-ScopeAcquireContext::~ScopeAcquireContext() {
- context.DoneCurrent();
-}
-
-} // namespace Core::Frontend
diff --git a/src/core/frontend/scope_acquire_context.h b/src/core/frontend/scope_acquire_context.h
deleted file mode 100644
index 7a65c0623..000000000
--- a/src/core/frontend/scope_acquire_context.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "common/common_types.h"
-
-namespace Core::Frontend {
-
-class GraphicsContext;
-
-/// Helper class to acquire/release window context within a given scope
-class ScopeAcquireContext : NonCopyable {
-public:
- explicit ScopeAcquireContext(Core::Frontend::GraphicsContext& context);
- ~ScopeAcquireContext();
-
-private:
- Core::Frontend::GraphicsContext& context;
-};
-
-} // namespace Core::Frontend
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d1bf13c89..557608e76 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -52,6 +52,11 @@ enum class LaunchParameterKind : u32 {
AccountPreselectedUser = 2,
};
+enum class VrMode : u8 {
+ Disabled = 0,
+ Enabled = 1,
+};
+
constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
struct LaunchParameterAccountPreselectedUser {
@@ -605,11 +610,11 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system,
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, nullptr, "GetReaderLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
- {50, nullptr, "IsVrModeEnabled"},
- {51, nullptr, "SetVrModeEnabled"},
+ {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
+ {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
{53, nullptr, "BeginVrModeEx"},
- {54, nullptr, "EndVrModeEx"},
+ {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
@@ -672,6 +677,30 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
rb.Push(static_cast<u8>(FocusState::InFocus));
}
+void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushEnum(VrMode::Disabled);
+}
+
+void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto is_vr_mode_enabled = rp.Pop<bool>();
+
+ LOG_WARNING(Service_AM, "(STUBBED) called. is_vr_mode_enabled={}", is_vr_mode_enabled);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ if (!is_vr_mode_enabled) {
+ rb.Push(RESULT_SUCCESS);
+ } else {
+ // TODO: Find better error code for this
+ UNIMPLEMENTED_MSG("is_vr_mode_enabled={}", is_vr_mode_enabled);
+ rb.Push(RESULT_UNKNOWN);
+ }
+}
+
void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
@@ -683,6 +712,13 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx
rb.Push(RESULT_SUCCESS);
}
+void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 0843de781..53cfce10f 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -182,7 +182,10 @@ private:
void GetOperationMode(Kernel::HLERequestContext& ctx);
void GetPerformanceMode(Kernel::HLERequestContext& ctx);
void GetBootMode(Kernel::HLERequestContext& ctx);
+ void IsVrModeEnabled(Kernel::HLERequestContext& ctx);
+ void SetVrModeEnabled(Kernel::HLERequestContext& ctx);
void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx);
+ void EndVrModeEx(Kernel::HLERequestContext& ctx);
void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index 907f464ab..26c8a7081 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -2,168 +2,24 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <memory>
-
#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/caps/caps_a.h"
+#include "core/hle/service/caps/caps_c.h"
+#include "core/hle/service/caps/caps_sc.h"
+#include "core/hle/service/caps/caps_ss.h"
+#include "core/hle/service/caps/caps_su.h"
+#include "core/hle/service/caps/caps_u.h"
#include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
namespace Service::Capture {
-class CAPS_A final : public ServiceFramework<CAPS_A> {
-public:
- explicit CAPS_A() : ServiceFramework{"caps:a"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetAlbumFileCount"},
- {1, nullptr, "GetAlbumFileList"},
- {2, nullptr, "LoadAlbumFile"},
- {3, nullptr, "DeleteAlbumFile"},
- {4, nullptr, "StorageCopyAlbumFile"},
- {5, nullptr, "IsAlbumMounted"},
- {6, nullptr, "GetAlbumUsage"},
- {7, nullptr, "GetAlbumFileSize"},
- {8, nullptr, "LoadAlbumFileThumbnail"},
- {9, nullptr, "LoadAlbumScreenShotImage"},
- {10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
- {11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
- {12, nullptr, "Unknown12"},
- {13, nullptr, "Unknown13"},
- {14, nullptr, "Unknown14"},
- {15, nullptr, "Unknown15"},
- {16, nullptr, "Unknown16"},
- {17, nullptr, "Unknown17"},
- {18, nullptr, "Unknown18"},
- {202, nullptr, "SaveEditedScreenShot"},
- {301, nullptr, "GetLastThumbnail"},
- {401, nullptr, "GetAutoSavingStorage"},
- {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
- {1001, nullptr, "Unknown1001"},
- {1002, nullptr, "Unknown1002"},
- {1003, nullptr, "Unknown1003"},
- {8001, nullptr, "ForceAlbumUnmounted"},
- {8002, nullptr, "ResetAlbumMountStatus"},
- {8011, nullptr, "RefreshAlbumCache"},
- {8012, nullptr, "GetAlbumCache"},
- {8013, nullptr, "Unknown8013"},
- {8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
- {10011, nullptr, "SetInternalErrorConversionEnabled"},
- {50000, nullptr, "Unknown50000"},
- {60002, nullptr, "Unknown60002"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class CAPS_C final : public ServiceFramework<CAPS_C> {
-public:
- explicit CAPS_C() : ServiceFramework{"caps:c"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {33, nullptr, "Unknown33"},
- {2001, nullptr, "Unknown2001"},
- {2002, nullptr, "Unknown2002"},
- {2011, nullptr, "Unknown2011"},
- {2012, nullptr, "Unknown2012"},
- {2013, nullptr, "Unknown2013"},
- {2014, nullptr, "Unknown2014"},
- {2101, nullptr, "Unknown2101"},
- {2102, nullptr, "Unknown2102"},
- {2201, nullptr, "Unknown2201"},
- {2301, nullptr, "Unknown2301"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class CAPS_SC final : public ServiceFramework<CAPS_SC> {
-public:
- explicit CAPS_SC() : ServiceFramework{"caps:sc"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1, nullptr, "Unknown1"},
- {2, nullptr, "Unknown2"},
- {1001, nullptr, "Unknown3"},
- {1002, nullptr, "Unknown4"},
- {1003, nullptr, "Unknown5"},
- {1011, nullptr, "Unknown6"},
- {1012, nullptr, "Unknown7"},
- {1201, nullptr, "Unknown8"},
- {1202, nullptr, "Unknown9"},
- {1203, nullptr, "Unknown10"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class CAPS_SS final : public ServiceFramework<CAPS_SS> {
-public:
- explicit CAPS_SS() : ServiceFramework{"caps:ss"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {201, nullptr, "Unknown1"},
- {202, nullptr, "Unknown2"},
- {203, nullptr, "Unknown3"},
- {204, nullptr, "Unknown4"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class CAPS_SU final : public ServiceFramework<CAPS_SU> {
-public:
- explicit CAPS_SU() : ServiceFramework{"caps:su"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {201, nullptr, "SaveScreenShot"},
- {203, nullptr, "SaveScreenShotEx0"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class CAPS_U final : public ServiceFramework<CAPS_U> {
-public:
- explicit CAPS_U() : ServiceFramework{"caps:u"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {32, nullptr, "SetShimLibraryVersion"},
- {102, nullptr, "GetAlbumFileListByAruid"},
- {103, nullptr, "DeleteAlbumFileByAruid"},
- {104, nullptr, "GetAlbumFileSizeByAruid"},
- {105, nullptr, "DeleteAlbumFileByAruidForDebug"},
- {110, nullptr, "LoadAlbumScreenShotImageByAruid"},
- {120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"},
- {130, nullptr, "PrecheckToCreateContentsByAruid"},
- {140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
- {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
- {142, nullptr, "GetAlbumFileList3AaeAruid"},
- {143, nullptr, "GetAlbumFileList4AaeUidAruid"},
- {60002, nullptr, "OpenAccessorSessionForApplication"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
void InstallInterfaces(SM::ServiceManager& sm) {
std::make_shared<CAPS_A>()->InstallAsService(sm);
std::make_shared<CAPS_C>()->InstallAsService(sm);
+ std::make_shared<CAPS_U>()->InstallAsService(sm);
std::make_shared<CAPS_SC>()->InstallAsService(sm);
std::make_shared<CAPS_SS>()->InstallAsService(sm);
std::make_shared<CAPS_SU>()->InstallAsService(sm);
- std::make_shared<CAPS_U>()->InstallAsService(sm);
}
} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h
index 471185dfa..fc70a4c27 100644
--- a/src/core/hle/service/caps/caps.h
+++ b/src/core/hle/service/caps/caps.h
@@ -4,12 +4,83 @@
#pragma once
+#include "core/hle/service/service.h"
+
namespace Service::SM {
class ServiceManager;
}
namespace Service::Capture {
+enum AlbumImageOrientation {
+ Orientation0 = 0,
+ Orientation1 = 1,
+ Orientation2 = 2,
+ Orientation3 = 3,
+};
+
+enum AlbumReportOption {
+ Disable = 0,
+ Enable = 1,
+};
+
+enum ContentType : u8 {
+ Screenshot = 0,
+ Movie = 1,
+ ExtraMovie = 3,
+};
+
+enum AlbumStorage : u8 {
+ NAND = 0,
+ SD = 1,
+};
+
+struct AlbumFileDateTime {
+ u16 year;
+ u8 month;
+ u8 day;
+ u8 hour;
+ u8 minute;
+ u8 second;
+ u8 uid;
+};
+
+struct AlbumEntry {
+ u64 size;
+ u64 application_id;
+ AlbumFileDateTime datetime;
+ AlbumStorage storage;
+ ContentType content;
+ u8 padding[6];
+};
+
+struct AlbumFileEntry {
+ u64 size;
+ u64 hash;
+ AlbumFileDateTime datetime;
+ AlbumStorage storage;
+ ContentType content;
+ u8 padding[5];
+ u8 unknown;
+};
+
+struct ApplicationAlbumEntry {
+ u64 size;
+ u64 hash;
+ AlbumFileDateTime datetime;
+ AlbumStorage storage;
+ ContentType content;
+ u8 padding[5];
+ u8 unknown;
+};
+
+struct ApplicationAlbumFileEntry {
+ ApplicationAlbumEntry entry;
+ AlbumFileDateTime datetime;
+ u64 unknown;
+};
+
+/// Registers all Capture services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& sm);
} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
new file mode 100644
index 000000000..88a3fdc05
--- /dev/null
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -0,0 +1,78 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/caps/caps_a.h"
+
+namespace Service::Capture {
+
+class IAlbumAccessorSession final : public ServiceFramework<IAlbumAccessorSession> {
+public:
+ explicit IAlbumAccessorSession() : ServiceFramework{"IAlbumAccessorSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {2001, nullptr, "OpenAlbumMovieReadStream"},
+ {2002, nullptr, "CloseAlbumMovieReadStream"},
+ {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
+ {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
+ {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
+ {2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"},
+ {2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"},
+ {2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+CAPS_A::CAPS_A() : ServiceFramework("caps:a") {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetAlbumFileCount"},
+ {1, nullptr, "GetAlbumFileList"},
+ {2, nullptr, "LoadAlbumFile"},
+ {3, nullptr, "DeleteAlbumFile"},
+ {4, nullptr, "StorageCopyAlbumFile"},
+ {5, nullptr, "IsAlbumMounted"},
+ {6, nullptr, "GetAlbumUsage"},
+ {7, nullptr, "GetAlbumFileSize"},
+ {8, nullptr, "LoadAlbumFileThumbnail"},
+ {9, nullptr, "LoadAlbumScreenShotImage"},
+ {10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
+ {11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
+ {12, nullptr, "LoadAlbumScreenShotImageEx"},
+ {13, nullptr, "LoadAlbumScreenShotThumbnailImageEx"},
+ {14, nullptr, "LoadAlbumScreenShotImageEx0"},
+ {15, nullptr, "GetAlbumUsage3"},
+ {16, nullptr, "GetAlbumMountResult"},
+ {17, nullptr, "GetAlbumUsage16"},
+ {18, nullptr, "Unknown18"},
+ {100, nullptr, "GetAlbumFileCountEx0"},
+ {101, nullptr, "GetAlbumFileListEx0"},
+ {202, nullptr, "SaveEditedScreenShot"},
+ {301, nullptr, "GetLastThumbnail"},
+ {302, nullptr, "GetLastOverlayMovieThumbnail"},
+ {401, nullptr, "GetAutoSavingStorage"},
+ {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
+ {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"},
+ {1002, nullptr, "LoadAlbumScreenShotImageEx1"},
+ {1003, nullptr, "LoadAlbumScreenShotThumbnailImageEx1"},
+ {8001, nullptr, "ForceAlbumUnmounted"},
+ {8002, nullptr, "ResetAlbumMountStatus"},
+ {8011, nullptr, "RefreshAlbumCache"},
+ {8012, nullptr, "GetAlbumCache"},
+ {8013, nullptr, "GetAlbumCacheEx"},
+ {8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
+ {10011, nullptr, "SetInternalErrorConversionEnabled"},
+ {50000, nullptr, "LoadMakerNoteInfoForDebug"},
+ {60002, nullptr, "OpenAccessorSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+CAPS_A::~CAPS_A() = default;
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h
new file mode 100644
index 000000000..8de832491
--- /dev/null
+++ b/src/core/hle/service/caps/caps_a.h
@@ -0,0 +1,21 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class HLERequestContext;
+}
+
+namespace Service::Capture {
+
+class CAPS_A final : public ServiceFramework<CAPS_A> {
+public:
+ explicit CAPS_A();
+ ~CAPS_A() override;
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp
new file mode 100644
index 000000000..ea6452ffa
--- /dev/null
+++ b/src/core/hle/service/caps/caps_c.cpp
@@ -0,0 +1,75 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/caps/caps_c.h"
+
+namespace Service::Capture {
+
+class IAlbumControlSession final : public ServiceFramework<IAlbumControlSession> {
+public:
+ explicit IAlbumControlSession() : ServiceFramework{"IAlbumControlSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {2001, nullptr, "OpenAlbumMovieReadStream"},
+ {2002, nullptr, "CloseAlbumMovieReadStream"},
+ {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
+ {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
+ {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
+ {2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"},
+ {2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"},
+ {2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"},
+ {2401, nullptr, "OpenAlbumMovieWriteStream"},
+ {2402, nullptr, "FinishAlbumMovieWriteStream"},
+ {2403, nullptr, "CommitAlbumMovieWriteStream"},
+ {2404, nullptr, "DiscardAlbumMovieWriteStream"},
+ {2405, nullptr, "DiscardAlbumMovieWriteStreamNoDelete"},
+ {2406, nullptr, "CommitAlbumMovieWriteStreamEx"},
+ {2411, nullptr, "StartAlbumMovieWriteStreamDataSection"},
+ {2412, nullptr, "EndAlbumMovieWriteStreamDataSection"},
+ {2413, nullptr, "StartAlbumMovieWriteStreamMetaSection"},
+ {2414, nullptr, "EndAlbumMovieWriteStreamMetaSection"},
+ {2421, nullptr, "ReadDataFromAlbumMovieWriteStream"},
+ {2422, nullptr, "WriteDataToAlbumMovieWriteStream"},
+ {2424, nullptr, "WriteMetaToAlbumMovieWriteStream"},
+ {2431, nullptr, "GetAlbumMovieWriteStreamBrokenReason"},
+ {2433, nullptr, "GetAlbumMovieWriteStreamDataSize"},
+ {2434, nullptr, "SetAlbumMovieWriteStreamDataSize"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+CAPS_C::CAPS_C() : ServiceFramework("caps:c") {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "CaptureRawImage"},
+ {2, nullptr, "CaptureRawImageWithTimeout"},
+ {33, nullptr, "Unknown33"},
+ {1001, nullptr, "RequestTakingScreenShot"},
+ {1002, nullptr, "RequestTakingScreenShotWithTimeout"},
+ {1011, nullptr, "NotifyTakingScreenShotRefused"},
+ {2001, nullptr, "NotifyAlbumStorageIsAvailable"},
+ {2002, nullptr, "NotifyAlbumStorageIsUnavailable"},
+ {2011, nullptr, "RegisterAppletResourceUserId"},
+ {2012, nullptr, "UnregisterAppletResourceUserId"},
+ {2013, nullptr, "GetApplicationIdFromAruid"},
+ {2014, nullptr, "CheckApplicationIdRegistered"},
+ {2101, nullptr, "GenerateCurrentAlbumFileId"},
+ {2102, nullptr, "GenerateApplicationAlbumEntry"},
+ {2201, nullptr, "SaveAlbumScreenShotFile"},
+ {2202, nullptr, "SaveAlbumScreenShotFileEx"},
+ {2301, nullptr, "SetOverlayScreenShotThumbnailData"},
+ {2302, nullptr, "SetOverlayMovieThumbnailData"},
+ {60001, nullptr, "OpenControlSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+CAPS_C::~CAPS_C() = default;
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h
new file mode 100644
index 000000000..d07cdb441
--- /dev/null
+++ b/src/core/hle/service/caps/caps_c.h
@@ -0,0 +1,21 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class HLERequestContext;
+}
+
+namespace Service::Capture {
+
+class CAPS_C final : public ServiceFramework<CAPS_C> {
+public:
+ explicit CAPS_C();
+ ~CAPS_C() override;
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_sc.cpp b/src/core/hle/service/caps/caps_sc.cpp
new file mode 100644
index 000000000..d01a8a58e
--- /dev/null
+++ b/src/core/hle/service/caps/caps_sc.cpp
@@ -0,0 +1,40 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/caps/caps_sc.h"
+
+namespace Service::Capture {
+
+CAPS_SC::CAPS_SC() : ServiceFramework("caps:sc") {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "CaptureRawImage"},
+ {2, nullptr, "CaptureRawImageWithTimeout"},
+ {3, nullptr, "AttachSharedBuffer"},
+ {5, nullptr, "CaptureRawImageToAttachedSharedBuffer"},
+ {210, nullptr, "Unknown210"},
+ {1001, nullptr, "RequestTakingScreenShot"},
+ {1002, nullptr, "RequestTakingScreenShotWithTimeout"},
+ {1003, nullptr, "RequestTakingScreenShotEx"},
+ {1004, nullptr, "RequestTakingScreenShotEx1"},
+ {1009, nullptr, "CancelTakingScreenShot"},
+ {1010, nullptr, "SetTakingScreenShotCancelState"},
+ {1011, nullptr, "NotifyTakingScreenShotRefused"},
+ {1012, nullptr, "NotifyTakingScreenShotFailed"},
+ {1101, nullptr, "SetupOverlayMovieThumbnail"},
+ {1106, nullptr, "Unknown1106"},
+ {1107, nullptr, "Unknown1107"},
+ {1201, nullptr, "OpenRawScreenShotReadStream"},
+ {1202, nullptr, "CloseRawScreenShotReadStream"},
+ {1203, nullptr, "ReadRawScreenShotReadStream"},
+ {1204, nullptr, "Unknown1204"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+CAPS_SC::~CAPS_SC() = default;
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_sc.h b/src/core/hle/service/caps/caps_sc.h
new file mode 100644
index 000000000..9ba372f7a
--- /dev/null
+++ b/src/core/hle/service/caps/caps_sc.h
@@ -0,0 +1,21 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class HLERequestContext;
+}
+
+namespace Service::Capture {
+
+class CAPS_SC final : public ServiceFramework<CAPS_SC> {
+public:
+ explicit CAPS_SC();
+ ~CAPS_SC() override;
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp
new file mode 100644
index 000000000..eaa3a7494
--- /dev/null
+++ b/src/core/hle/service/caps/caps_ss.cpp
@@ -0,0 +1,26 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/caps/caps_ss.h"
+
+namespace Service::Capture {
+
+CAPS_SS::CAPS_SS() : ServiceFramework("caps:ss") {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {201, nullptr, "SaveScreenShot"},
+ {202, nullptr, "SaveEditedScreenShot"},
+ {203, nullptr, "SaveScreenShotEx0"},
+ {204, nullptr, "SaveEditedScreenShotEx0"},
+ {206, nullptr, "Unknown206"},
+ {208, nullptr, "SaveScreenShotOfMovieEx1"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+CAPS_SS::~CAPS_SS() = default;
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_ss.h b/src/core/hle/service/caps/caps_ss.h
new file mode 100644
index 000000000..e258a6925
--- /dev/null
+++ b/src/core/hle/service/caps/caps_ss.h
@@ -0,0 +1,21 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class HLERequestContext;
+}
+
+namespace Service::Capture {
+
+class CAPS_SS final : public ServiceFramework<CAPS_SS> {
+public:
+ explicit CAPS_SS();
+ ~CAPS_SS() override;
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp
new file mode 100644
index 000000000..2b4c2d808
--- /dev/null
+++ b/src/core/hle/service/caps/caps_su.cpp
@@ -0,0 +1,22 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/caps/caps_su.h"
+
+namespace Service::Capture {
+
+CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {201, nullptr, "SaveScreenShot"},
+ {203, nullptr, "SaveScreenShotEx0"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+CAPS_SU::~CAPS_SU() = default;
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h
new file mode 100644
index 000000000..cb11f7c9a
--- /dev/null
+++ b/src/core/hle/service/caps/caps_su.h
@@ -0,0 +1,21 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class HLERequestContext;
+}
+
+namespace Service::Capture {
+
+class CAPS_SU final : public ServiceFramework<CAPS_SU> {
+public:
+ explicit CAPS_SU();
+ ~CAPS_SU() override;
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp
new file mode 100644
index 000000000..78bab6ed8
--- /dev/null
+++ b/src/core/hle/service/caps/caps_u.cpp
@@ -0,0 +1,76 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/caps/caps_u.h"
+
+namespace Service::Capture {
+
+class IAlbumAccessorApplicationSession final
+ : public ServiceFramework<IAlbumAccessorApplicationSession> {
+public:
+ explicit IAlbumAccessorApplicationSession()
+ : ServiceFramework{"IAlbumAccessorApplicationSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {2001, nullptr, "OpenAlbumMovieReadStream"},
+ {2002, nullptr, "CloseAlbumMovieReadStream"},
+ {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"},
+ {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"},
+ {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+CAPS_U::CAPS_U() : ServiceFramework("caps:u") {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {31, nullptr, "GetShimLibraryVersion"},
+ {32, nullptr, "SetShimLibraryVersion"},
+ {102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"},
+ {103, nullptr, "DeleteAlbumContentsFileForApplication"},
+ {104, nullptr, "GetAlbumContentsFileSizeForApplication"},
+ {105, nullptr, "DeleteAlbumFileByAruidForDebug"},
+ {110, nullptr, "LoadAlbumContentsFileScreenShotImageForApplication"},
+ {120, nullptr, "LoadAlbumContentsFileThumbnailImageForApplication"},
+ {130, nullptr, "PrecheckToCreateContentsForApplication"},
+ {140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
+ {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
+ {142, nullptr, "GetAlbumFileList3AaeAruid"},
+ {143, nullptr, "GetAlbumFileList4AaeUidAruid"},
+ {60002, nullptr, "OpenAccessorSessionForApplication"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+CAPS_U::~CAPS_U() = default;
+
+void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) {
+ // Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an
+ // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total
+ // output entries (which is copied to a s32 by official SW).
+ IPC::RequestParser rp{ctx};
+ [[maybe_unused]] const auto application_album_file_entries = rp.PopRaw<std::array<u8, 0x30>>();
+ const auto pid = rp.Pop<s32>();
+ const auto content_type = rp.PopRaw<ContentType>();
+ [[maybe_unused]] const auto start_datetime = rp.PopRaw<AlbumFileDateTime>();
+ [[maybe_unused]] const auto end_datetime = rp.PopRaw<AlbumFileDateTime>();
+ const auto applet_resource_user_id = rp.Pop<u64>();
+ LOG_WARNING(Service_Capture,
+ "(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid,
+ content_type, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<s32>(0);
+}
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h
new file mode 100644
index 000000000..e6e0716ff
--- /dev/null
+++ b/src/core/hle/service/caps/caps_u.h
@@ -0,0 +1,24 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class HLERequestContext;
+}
+
+namespace Service::Capture {
+
+class CAPS_U final : public ServiceFramework<CAPS_U> {
+public:
+ explicit CAPS_U();
+ ~CAPS_U() override;
+
+private:
+ void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx);
+};
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index e6b56a9f9..d6ed5f304 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -235,7 +235,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
{303, nullptr, "ActivateSevenSixAxisSensor"},
{304, nullptr, "StartSevenSixAxisSensor"},
{305, nullptr, "StopSevenSixAxisSensor"},
- {306, nullptr, "InitializeSevenSixAxisSensor"},
+ {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
{307, nullptr, "FinalizeSevenSixAxisSensor"},
{308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
{309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
@@ -853,6 +853,13 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
+void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
class HidDbg final : public ServiceFramework<HidDbg> {
public:
explicit HidDbg() : ServiceFramework{"hid:dbg"} {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index ad20f147c..039c38b58 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -128,6 +128,7 @@ private:
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
+ void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx);
std::shared_ptr<IAppletResource> applet_resource;
Core::System& system;
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp
index 1660bbdb8..f509653a3 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/interface.cpp
@@ -30,7 +30,7 @@ Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* nam
{400, &Time::GetClockSnapshot, "GetClockSnapshot"},
{401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
{500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
- {501, nullptr, "CalculateSpanBetween"},
+ {501, &Time::CalculateSpanBetween, "CalculateSpanBetween"},
};
// clang-format on
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 749b7be70..ce859f18d 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -308,6 +308,35 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
}
+void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
+ IPC::RequestParser rp{ctx};
+ const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>();
+ const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>();
+
+ Clock::TimeSpanType time_span_type{};
+ s64 span{};
+ if (const ResultCode result{snapshot_a.steady_clock_time_point.GetSpanBetween(
+ snapshot_b.steady_clock_time_point, span)};
+ result != RESULT_SUCCESS) {
+ if (snapshot_a.network_time && snapshot_b.network_time) {
+ time_span_type =
+ Clock::TimeSpanType::FromSeconds(snapshot_b.network_time - snapshot_a.network_time);
+ } else {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ERROR_TIME_NOT_FOUND);
+ return;
+ }
+ } else {
+ time_span_type = Clock::TimeSpanType::FromSeconds(span);
+ }
+
+ IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushRaw(time_span_type.nanoseconds);
+}
+
void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index aadc2df60..351988468 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -32,6 +32,7 @@ public:
void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx);
void GetClockSnapshot(Kernel::HLERequestContext& ctx);
void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx);
+ void CalculateSpanBetween(Kernel::HLERequestContext& ctx);
void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
private: