Преглед изворни кода

Impl'd IsUserAccountSwitchLocked, SetAudioOutVolume, GetAudioOutVolume & Partial impl of GetAccumulatedSuspendedTickChangedEvent

IPC-100 was changed to InitializeApplicationInfoOld instead of InitializeApplicationInfo. IPC-150 makes an indentical call to IPC-100 however does extra processing. They should not have the same name as it's quite confusing to debug.
David Marcec пре 7 година
родитељ
комит
335127af69

+ 7 - 3
src/audio_core/stream.cpp

@@ -51,6 +51,10 @@ void Stream::Stop() {
     UNIMPLEMENTED();
 }
 
+void Stream::SetVolume(float volume) {
+    game_volume = volume;
+}
+
 Stream::State Stream::GetState() const {
     return state;
 }
@@ -62,8 +66,8 @@ s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const {
     return Core::Timing::usToCycles(us);
 }
 
-static void VolumeAdjustSamples(std::vector<s16>& samples) {
-    const float volume{std::clamp(Settings::values.volume, 0.0f, 1.0f)};
+static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
+    const float volume{std::clamp(Settings::values.volume - (1.0f - game_volume), 0.0f, 1.0f)};
 
     if (volume == 1.0f) {
         return;
@@ -97,7 +101,7 @@ void Stream::PlayNextBuffer() {
     active_buffer = queued_buffers.front();
     queued_buffers.pop();
 
-    VolumeAdjustSamples(active_buffer->GetSamples());
+    VolumeAdjustSamples(active_buffer->GetSamples(), game_volume);
 
     sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
 

+ 7 - 0
src/audio_core/stream.h

@@ -61,6 +61,12 @@ public:
     /// Returns a vector of recently released buffers specified by tag
     std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(std::size_t max_count);
 
+    void SetVolume(float volume);
+
+    float GetVolume() const {
+        return game_volume;
+    }
+
     /// Returns true if the stream is currently playing
     bool IsPlaying() const {
         return state == State::Playing;
@@ -103,6 +109,7 @@ private:
     SinkStream& sink_stream;                  ///< Output sink for the stream
     Core::Timing::CoreTiming& core_timing;    ///< Core timing instance.
     std::string name;                         ///< Name of the stream, must be unique
+    float game_volume = 1.0f;                 ///< The volume the game currently has set
 };
 
 using StreamPtr = std::shared_ptr<Stream>;

+ 4 - 0
src/core/file_sys/control_metadata.cpp

@@ -87,6 +87,10 @@ u64 NACP::GetDefaultJournalSaveSize() const {
     return raw.user_account_save_data_journal_size;
 }
 
+bool NACP::GetUserAccountSwitchLock() const {
+    return raw.user_account_switch_lock == 1;
+}
+
 u32 NACP::GetSupportedLanguages() const {
     return raw.supported_languages;
 }

+ 3 - 1
src/core/file_sys/control_metadata.h

@@ -30,7 +30,8 @@ struct RawNACP {
     std::array<LanguageEntry, 16> language_entries;
     std::array<u8, 0x25> isbn;
     u8 startup_user_account;
-    INSERT_PADDING_BYTES(2);
+    u8 user_account_switch_lock;
+    u8 addon_content_registration_type;
     u32_le application_attribute;
     u32_le supported_languages;
     u32_le parental_control;
@@ -111,6 +112,7 @@ public:
     u64 GetDefaultJournalSaveSize() const;
     u32 GetSupportedLanguages() const;
     std::vector<u8> GetRawBytes() const;
+    bool GetUserAccountSwitchLock() const;
 
 private:
     RawNACP raw{};

+ 28 - 1
src/core/hle/service/acc/acc.cpp

@@ -12,13 +12,17 @@
 #include "common/swap.h"
 #include "core/constants.h"
 #include "core/core_timing.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/process.h"
 #include "core/hle/service/acc/acc.h"
 #include "core/hle/service/acc/acc_aa.h"
 #include "core/hle/service/acc/acc_su.h"
 #include "core/hle/service/acc/acc_u0.h"
 #include "core/hle/service/acc/acc_u1.h"
 #include "core/hle/service/acc/profile_manager.h"
+#include "core/loader/loader.h"
 
 namespace Service::Account {
 
@@ -213,7 +217,7 @@ void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestCon
     rb.Push(profile_manager->CanSystemRegisterUser());
 }
 
-void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
+void Module::Interface::InitializeApplicationInfoOld(Kernel::HLERequestContext& ctx) {
     LOG_WARNING(Service_ACC, "(STUBBED) called");
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(RESULT_SUCCESS);
@@ -226,6 +230,29 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo
     rb.PushIpcInterface<IManagerForApplication>();
 }
 
+void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_ACC, "called");
+    FileSys::NACP nacp;
+    const auto res = Core::System::GetInstance().GetAppLoader().ReadControlData(nacp);
+
+    bool is_locked = false;
+
+    if (res != Loader::ResultStatus::Success) {
+        FileSys::PatchManager pm{Core::CurrentProcess()->GetTitleID()};
+        auto [nacp_unique, discard] = pm.GetControlMetadata();
+
+        if (nacp_unique != nullptr) {
+            is_locked = nacp_unique->GetUserAccountSwitchLock();
+        }
+    } else {
+        is_locked = nacp.GetUserAccountSwitchLock();
+    }
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushRaw<u8>(is_locked);
+}
+
 void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service_ACC, "called");
     // A u8 is passed into this function which we can safely ignore. It's to determine if we have

+ 2 - 1
src/core/hle/service/acc/acc.h

@@ -24,10 +24,11 @@ public:
         void ListOpenUsers(Kernel::HLERequestContext& ctx);
         void GetLastOpenedUser(Kernel::HLERequestContext& ctx);
         void GetProfile(Kernel::HLERequestContext& ctx);
-        void InitializeApplicationInfo(Kernel::HLERequestContext& ctx);
+        void InitializeApplicationInfoOld(Kernel::HLERequestContext& ctx);
         void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx);
         void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx);
         void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx);
+        void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx);
 
     protected:
         std::shared_ptr<Module> module;

+ 2 - 2
src/core/hle/service/acc/acc_u0.cpp

@@ -21,7 +21,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
         {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
         {60, nullptr, "ListOpenContextStoredUsers"},
         {99, nullptr, "DebugActivateOpenContextRetention"},
-        {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
+        {100, &ACC_U0::InitializeApplicationInfoOld, "InitializeApplicationInfoOld"},
         {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
         {102, nullptr, "AuthenticateApplicationAsync"},
         {103, nullptr, "CheckNetworkServiceAvailabilityAsync"},
@@ -32,7 +32,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
         {131, nullptr, "ListOpenContextStoredUsers"},
         {140, nullptr, "InitializeApplicationInfo"},
         {141, nullptr, "ListQualifiedUsers"},
-        {150, nullptr, "IsUserAccountSwitchLocked"},
+        {150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"},
     };
     // clang-format on
 

+ 16 - 1
src/core/hle/service/am/am.cpp

@@ -271,7 +271,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
         {71, nullptr, "GetCurrentIlluminanceEx"},
         {80, nullptr, "SetWirelessPriorityMode"},
         {90, nullptr, "GetAccumulatedSuspendedTickValue"},
-        {91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"},
+        {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
         {100, nullptr, "SetAlbumImageTakenNotificationEnabled"},
         {1000, nullptr, "GetDebugStorageChannel"},
     };
@@ -282,6 +282,10 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
     auto& kernel = Core::System::GetInstance().Kernel();
     launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
                                                               "ISelfController:LaunchableEvent");
+
+    // TODO(ogniK): Figure out where, when and why this event gets signalled
+    accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair(
+        kernel, Kernel::ResetType::Manual, "ISelfController:AccumulatedSuspendedTickChangedEvent");
 }
 
 ISelfController::~ISelfController() = default;
@@ -444,6 +448,17 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c
     rb.Push<u32>(idle_time_detection_extension);
 }
 
+void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx) {
+    // The implementation of this function is fine as is, the reason we're labelling it as stubbed
+    // is because we're currently unsure when and where accumulated_suspended_tick_changed_event is
+    // actually signalled for the time being.
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(RESULT_SUCCESS);
+    rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable);
+}
+
 AppletMessageQueue::AppletMessageQueue() {
     auto& kernel = Core::System::GetInstance().Kernel();
     on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,

+ 3 - 0
src/core/hle/service/am/am.h

@@ -133,9 +133,12 @@ private:
     void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);
     void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
     void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
+    void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx);
 
     std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
     Kernel::EventPair launchable_event;
+    Kernel::EventPair accumulated_suspended_tick_changed_event;
+
     u32 idle_time_detection_extension = 0;
     u64 num_fatal_sections_entered = 0;
 };

+ 21 - 2
src/core/hle/service/audio/audout_u.cpp

@@ -58,8 +58,8 @@ public:
             {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
             {10, nullptr, "GetAudioOutPlayedSampleCount"},
             {11, nullptr, "FlushAudioOutBuffers"},
-            {12, nullptr, "SetAudioOutVolume"},
-            {13, nullptr, "GetAudioOutVolume"},
+            {12, &IAudioOut::SetAudioOutVolume, "SetAudioOutVolume"},
+            {13, &IAudioOut::GetAudioOutVolume, "GetAudioOutVolume"},
         };
         // clang-format on
         RegisterHandlers(functions);
@@ -183,6 +183,25 @@ private:
         rb.Push(static_cast<u32>(stream->GetQueueSize()));
     }
 
+    void SetAudioOutVolume(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        float volume = rp.PopRaw<float>();
+        LOG_DEBUG(Service_Audio, "called, volume={}", volume);
+
+        stream->SetVolume(volume);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+    }
+
+    void GetAudioOutVolume(Kernel::HLERequestContext& ctx) {
+        LOG_DEBUG(Service_Audio, "called");
+
+        IPC::ResponseBuilder rb{ctx, 3};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushRaw<float>(stream->GetVolume());
+    }
+
     AudioCore::AudioOut& audio_core;
     AudioCore::StreamPtr stream;
     std::string device_name;