diff options
Diffstat (limited to 'src/core/hle')
22 files changed, 333 insertions, 89 deletions
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 5ee5c05e3..1bf79b692 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -12,12 +12,23 @@ #include "core/hle/kernel/thread.h" namespace Kernel { +namespace { +constexpr u16 GetSlot(Handle handle) { + return handle >> 15; +} + +constexpr u16 GetGeneration(Handle handle) { + return handle & 0x7FFF; +} +} // Anonymous namespace HandleTable::HandleTable() { next_generation = 1; Clear(); } +HandleTable::~HandleTable() = default; + ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { DEBUG_ASSERT(obj != nullptr); diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index 9e2f33e8a..e3f3e3fb8 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -43,6 +43,7 @@ enum KernelHandle : Handle { class HandleTable final : NonCopyable { public: HandleTable(); + ~HandleTable(); /** * Allocates a handle for the given object. @@ -89,18 +90,8 @@ public: void Clear(); private: - /** - * This is the maximum limit of handles allowed per process in CTR-OS. It can be further - * reduced by ExHeader values, but this is not emulated here. - */ - static const std::size_t MAX_COUNT = 4096; - - static u16 GetSlot(Handle handle) { - return handle >> 15; - } - static u16 GetGeneration(Handle handle) { - return handle & 0x7FFF; - } + /// This is the maximum limit of handles allowed per process in Horizon + static constexpr std::size_t MAX_COUNT = 1024; /// Stores the Object referenced by the handle or null if the slot is empty. std::array<SharedPtr<Object>, MAX_COUNT> objects; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b8b6b4d49..f287f7c97 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -671,7 +671,8 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) break; } default: - UNIMPLEMENTED(); + LOG_WARNING(Kernel_SVC, "(STUBBED) Unimplemented svcGetInfo id=0x{:016X}", info_id); + return ERR_INVALID_ENUM_VALUE; } return RESULT_SUCCESS; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 7b4af9eb7..4f17b52f9 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -6,8 +6,6 @@ #include <cinttypes> #include <cstring> #include <stack> -#include "applets/applets.h" -#include "applets/software_keyboard.h" #include "audio_core/audio_renderer.h" #include "core/core.h" #include "core/hle/ipc_helpers.h" @@ -18,6 +16,9 @@ #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" +#include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/applets/software_keyboard.h" +#include "core/hle/service/am/applets/stub_applet.h" #include "core/hle/service/am/idle.h" #include "core/hle/service/am/omm.h" #include "core/hle/service/am/spsm.h" @@ -482,11 +483,15 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& rb.Push(RESULT_SUCCESS); if (Settings::values.use_docked_mode) { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * + static_cast<u32>(Settings::values.resolution_factor)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * + static_cast<u32>(Settings::values.resolution_factor)); } else { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * + static_cast<u32>(Settings::values.resolution_factor)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * + static_cast<u32>(Settings::values.resolution_factor)); } LOG_DEBUG(Service_AM, "called"); @@ -532,8 +537,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { public: explicit ILibraryAppletAccessor(std::shared_ptr<Applets::Applet> applet) - : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)), - broker(std::make_shared<Applets::AppletDataBroker>()) { + : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, @@ -562,7 +566,7 @@ public: private: void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { - const auto event = broker->GetStateChangedEvent(); + const auto event = applet->GetBroker().GetStateChangedEvent(); event->Signal(); IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -590,7 +594,7 @@ private: void Start(Kernel::HLERequestContext& ctx) { ASSERT(applet != nullptr); - applet->Initialize(broker); + applet->Initialize(); applet->Execute(); IPC::ResponseBuilder rb{ctx, 2}; @@ -601,7 +605,7 @@ private: void PushInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - broker->PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>()); + applet->GetBroker().PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -612,7 +616,7 @@ private: void PopOutData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - const auto storage = broker->PopNormalDataToGame(); + const auto storage = applet->GetBroker().PopNormalDataToGame(); if (storage == nullptr) { rb.Push(ERR_NO_DATA_IN_CHANNEL); return; @@ -626,7 +630,7 @@ private: void PushInteractiveInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - broker->PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>()); + applet->GetBroker().PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>()); ASSERT(applet->IsInitialized()); applet->ExecuteInteractive(); @@ -641,7 +645,7 @@ private: void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - const auto storage = broker->PopInteractiveDataToGame(); + const auto storage = applet->GetBroker().PopInteractiveDataToGame(); if (storage == nullptr) { rb.Push(ERR_NO_DATA_IN_CHANNEL); return; @@ -656,7 +660,7 @@ private: void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(broker->GetNormalDataEvent()); + rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent()); LOG_DEBUG(Service_AM, "called"); } @@ -664,13 +668,12 @@ private: void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(broker->GetInteractiveDataEvent()); + rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent()); LOG_DEBUG(Service_AM, "called"); } std::shared_ptr<Applets::Applet> applet; - std::shared_ptr<Applets::AppletDataBroker> broker; }; void IStorage::Open(Kernel::HLERequestContext& ctx) { @@ -763,8 +766,9 @@ static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) { case AppletId::SoftwareKeyboard: return std::make_shared<Applets::SoftwareKeyboard>(); default: - UNREACHABLE_MSG("Unimplemented AppletId [{:08X}]!", static_cast<u32>(id)); - return nullptr; + LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!", + static_cast<u32>(id)); + return std::make_shared<Applets::StubApplet>(); } } diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 8adb81823..becbadd06 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -98,10 +98,8 @@ Applet::Applet() = default; Applet::~Applet() = default; -void Applet::Initialize(std::shared_ptr<AppletDataBroker> broker_) { - broker = std::move(broker_); - - const auto common = broker->PopNormalDataToApplet(); +void Applet::Initialize() { + const auto common = broker.PopNormalDataToApplet(); ASSERT(common != nullptr); const auto common_data = common->GetData(); diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 136445649..f65ea119c 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -4,14 +4,17 @@ #pragma once -#include <functional> #include <memory> #include <queue> #include "common/swap.h" -#include "core/hle/kernel/event.h" +#include "core/hle/kernel/kernel.h" union ResultCode; +namespace Kernel { +class Event; +} + namespace Service::AM { class IStorage; @@ -43,19 +46,26 @@ public: private: // Queues are named from applet's perspective - std::queue<std::unique_ptr<IStorage>> - in_channel; // PopNormalDataToApplet and PushNormalDataFromGame - std::queue<std::unique_ptr<IStorage>> - out_channel; // PopNormalDataToGame and PushNormalDataFromApplet - std::queue<std::unique_ptr<IStorage>> - in_interactive_channel; // PopInteractiveDataToApplet and PushInteractiveDataFromGame - std::queue<std::unique_ptr<IStorage>> - out_interactive_channel; // PopInteractiveDataToGame and PushInteractiveDataFromApplet + + // PopNormalDataToApplet and PushNormalDataFromGame + std::queue<std::unique_ptr<IStorage>> in_channel; + + // PopNormalDataToGame and PushNormalDataFromApplet + std::queue<std::unique_ptr<IStorage>> out_channel; + + // PopInteractiveDataToApplet and PushInteractiveDataFromGame + std::queue<std::unique_ptr<IStorage>> in_interactive_channel; + + // PopInteractiveDataToGame and PushInteractiveDataFromApplet + std::queue<std::unique_ptr<IStorage>> out_interactive_channel; Kernel::SharedPtr<Kernel::Event> state_changed_event; - Kernel::SharedPtr<Kernel::Event> pop_out_data_event; // Signaled on PushNormalDataFromApplet - Kernel::SharedPtr<Kernel::Event> - pop_interactive_out_data_event; // Signaled on PushInteractiveDataFromApplet + + // Signaled on PushNormalDataFromApplet + Kernel::SharedPtr<Kernel::Event> pop_out_data_event; + + // Signaled on PushInteractiveDataFromApplet + Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event; }; class Applet { @@ -63,7 +73,7 @@ public: Applet(); virtual ~Applet(); - virtual void Initialize(std::shared_ptr<AppletDataBroker> broker); + virtual void Initialize(); virtual bool TransactionComplete() const = 0; virtual ResultCode GetStatus() const = 0; @@ -74,6 +84,14 @@ public: return initialized; } + AppletDataBroker& GetBroker() { + return broker; + } + + const AppletDataBroker& GetBroker() const { + return broker; + } + protected: struct CommonArguments { u32_le arguments_version; @@ -85,8 +103,8 @@ protected: }; static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); - CommonArguments common_args; - std::shared_ptr<AppletDataBroker> broker; + CommonArguments common_args{}; + AppletDataBroker broker; bool initialized = false; }; diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index c4b76a515..981bdec51 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -42,21 +42,21 @@ SoftwareKeyboard::SoftwareKeyboard() = default; SoftwareKeyboard::~SoftwareKeyboard() = default; -void SoftwareKeyboard::Initialize(std::shared_ptr<AppletDataBroker> broker_) { +void SoftwareKeyboard::Initialize() { complete = false; initial_text.clear(); final_data.clear(); - Applet::Initialize(std::move(broker_)); + Applet::Initialize(); - const auto keyboard_config_storage = broker->PopNormalDataToApplet(); + const auto keyboard_config_storage = broker.PopNormalDataToApplet(); ASSERT(keyboard_config_storage != nullptr); const auto& keyboard_config = keyboard_config_storage->GetData(); ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); - const auto work_buffer_storage = broker->PopNormalDataToApplet(); + const auto work_buffer_storage = broker.PopNormalDataToApplet(); ASSERT(work_buffer_storage != nullptr); const auto& work_buffer = work_buffer_storage->GetData(); @@ -81,7 +81,7 @@ void SoftwareKeyboard::ExecuteInteractive() { if (complete) return; - const auto storage = broker->PopInteractiveDataToApplet(); + const auto storage = broker.PopInteractiveDataToApplet(); ASSERT(storage != nullptr); const auto data = storage->GetData(); const auto status = static_cast<bool>(data[0]); @@ -95,13 +95,13 @@ void SoftwareKeyboard::ExecuteInteractive() { std::memcpy(string.data(), data.data() + 4, string.size() * 2); frontend.SendTextCheckDialog( Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()), - [this] { broker->SignalStateChanged(); }); + [this] { broker.SignalStateChanged(); }); } } void SoftwareKeyboard::Execute() { if (complete) { - broker->PushNormalDataFromApplet(IStorage{final_data}); + broker.PushNormalDataFromApplet(IStorage{final_data}); return; } @@ -145,17 +145,17 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { final_data = output_main; if (complete) { - broker->PushNormalDataFromApplet(IStorage{output_main}); + broker.PushNormalDataFromApplet(IStorage{output_main}); } else { - broker->PushInteractiveDataFromApplet(IStorage{output_sub}); + broker.PushInteractiveDataFromApplet(IStorage{output_sub}); } - broker->SignalStateChanged(); + broker.SignalStateChanged(); } else { output_main[0] = 1; complete = true; - broker->PushNormalDataFromApplet(IStorage{output_main}); - broker->SignalStateChanged(); + broker.PushNormalDataFromApplet(IStorage{output_main}); + broker.SignalStateChanged(); } } } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 16e1fff66..efd5753a1 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -4,7 +4,12 @@ #pragma once +#include <array> +#include <string> +#include <vector> + #include "common/common_funcs.h" +#include "common/swap.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" @@ -50,7 +55,7 @@ public: SoftwareKeyboard(); ~SoftwareKeyboard() override; - void Initialize(std::shared_ptr<AppletDataBroker> broker) override; + void Initialize() override; bool TransactionComplete() const override; ResultCode GetStatus() const override; diff --git a/src/core/hle/service/am/applets/stub_applet.cpp b/src/core/hle/service/am/applets/stub_applet.cpp new file mode 100644 index 000000000..ed166b87d --- /dev/null +++ b/src/core/hle/service/am/applets/stub_applet.cpp @@ -0,0 +1,70 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <string> + +#include "common/hex_util.h" +#include "common/logging/log.h" +#include "core/hle/result.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applets/stub_applet.h" + +namespace Service::AM::Applets { + +static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) { + std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet(); + for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { + const auto data = storage->GetData(); + LOG_INFO(Service_AM, + "called (STUBBED), during {} recieved normal data with size={:08X}, data={}", + prefix, data.size(), Common::HexVectorToString(data)); + } + + storage = broker.PopInteractiveDataToApplet(); + for (; storage != nullptr; storage = broker.PopInteractiveDataToApplet()) { + const auto data = storage->GetData(); + LOG_INFO(Service_AM, + "called (STUBBED), during {} recieved interactive data with size={:08X}, data={}", + prefix, data.size(), Common::HexVectorToString(data)); + } +} + +StubApplet::StubApplet() = default; + +StubApplet::~StubApplet() = default; + +void StubApplet::Initialize() { + LOG_WARNING(Service_AM, "called (STUBBED)"); + Applet::Initialize(); + LogCurrentStorage(broker, "Initialize"); +} + +bool StubApplet::TransactionComplete() const { + LOG_WARNING(Service_AM, "called (STUBBED)"); + return true; +} + +ResultCode StubApplet::GetStatus() const { + LOG_WARNING(Service_AM, "called (STUBBED)"); + return RESULT_SUCCESS; +} + +void StubApplet::ExecuteInteractive() { + LOG_WARNING(Service_AM, "called (STUBBED)"); + LogCurrentStorage(broker, "ExecuteInteractive"); + + broker.PushNormalDataFromApplet(IStorage{std::vector<u8>(0x1000)}); + broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); + broker.SignalStateChanged(); +} + +void StubApplet::Execute() { + LOG_WARNING(Service_AM, "called (STUBBED)"); + LogCurrentStorage(broker, "Execute"); + + broker.PushNormalDataFromApplet(IStorage{std::vector<u8>(0x1000)}); + broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); + broker.SignalStateChanged(); +} +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/stub_applet.h b/src/core/hle/service/am/applets/stub_applet.h new file mode 100644 index 000000000..7d8dc968d --- /dev/null +++ b/src/core/hle/service/am/applets/stub_applet.h @@ -0,0 +1,24 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/am/applets/applets.h" + +namespace Service::AM::Applets { + +class StubApplet final : public Applet { +public: + StubApplet(); + ~StubApplet() override; + + void Initialize() override; + + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; +}; + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index ff1edefbb..23e1f1165 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -44,8 +44,10 @@ enum class AudioState : u32 { class IAudioOut final : public ServiceFramework<IAudioOut> { public: - IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core) - : ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params) { + IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core, std::string&& device_name, + std::string&& unique_name) + : ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params), + device_name(std::move(device_name)) { static const FunctionInfo functions[] = { {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, @@ -69,7 +71,7 @@ public: Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count, - "IAudioOut", [=]() { buffer_event->Signal(); }); + std::move(unique_name), [=]() { buffer_event->Signal(); }); } private: @@ -177,6 +179,7 @@ private: AudioCore::AudioOut& audio_core; AudioCore::StreamPtr stream; + std::string device_name; AudoutParams audio_params{}; @@ -199,7 +202,15 @@ void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) { void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); - ctx.WriteBuffer(DefaultDevice); + const auto device_name_data{ctx.ReadBuffer()}; + std::string device_name; + if (device_name_data[0] != '\0') { + device_name.assign(device_name_data.begin(), device_name_data.end()); + } else { + device_name.assign(DefaultDevice.begin(), DefaultDevice.end()); + } + ctx.WriteBuffer(device_name); + IPC::RequestParser rp{ctx}; auto params{rp.PopRaw<AudoutParams>()}; if (params.channel_count <= 2) { @@ -212,10 +223,9 @@ void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) { params.sample_rate = DefaultSampleRate; } - // TODO(bunnei): Support more than one IAudioOut interface. When we add this, ListAudioOutsImpl - // will likely need to be updated as well. - ASSERT_MSG(!audio_out_interface, "Unimplemented"); - audio_out_interface = std::make_shared<IAudioOut>(params, *audio_core); + std::string unique_name{fmt::format("{}-{}", device_name, audio_out_interfaces.size())}; + auto audio_out_interface = std::make_shared<IAudioOut>( + params, *audio_core, std::move(device_name), std::move(unique_name)); IPC::ResponseBuilder rb{ctx, 6, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -224,6 +234,8 @@ void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) { rb.Push<u32>(static_cast<u32>(AudioCore::Codec::PcmFormat::Int16)); rb.Push<u32>(static_cast<u32>(AudioState::Stopped)); rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface); + + audio_out_interfaces.push_back(std::move(audio_out_interface)); } AudOutU::AudOutU() : ServiceFramework("audout:u") { diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h index dcaf64708..aed4c43b2 100644 --- a/src/core/hle/service/audio/audout_u.h +++ b/src/core/hle/service/audio/audout_u.h @@ -4,6 +4,7 @@ #pragma once +#include <vector> #include "core/hle/service/service.h" namespace AudioCore { @@ -24,7 +25,7 @@ public: ~AudOutU() override; private: - std::shared_ptr<IAudioOut> audio_out_interface; + std::vector<std::shared_ptr<IAudioOut>> audio_out_interfaces; std::unique_ptr<AudioCore::AudioOut> audio_core; void ListAudioOutsImpl(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 5d6294016..2aa77f68d 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -341,6 +341,10 @@ std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() { return registered_cache_union; } +void ClearUnionContents() { + registered_cache_union = nullptr; +} + FileSys::RegisteredCache* GetSystemNANDContents() { LOG_TRACE(Service_FS, "Opening System NAND Contents"); @@ -391,6 +395,7 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { bis_factory = nullptr; save_data_factory = nullptr; sdmc_factory = nullptr; + ClearUnionContents(); } auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index ff9182e84..0a6cb6635 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -49,6 +49,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) ResultVal<FileSys::VirtualDir> OpenSDMC(); std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); +void ClearUnionContents(); FileSys::RegisteredCache* GetSystemNANDContents(); FileSys::RegisteredCache* GetUserNANDContents(); diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index e76c83aee..c22357d8c 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -71,8 +71,9 @@ void Controller_DebugPad::OnUpdate(u8* data, std::size_t size) { void Controller_DebugPad::OnLoadInputDevices() { std::transform(Settings::values.debug_pad_buttons.begin(), - Settings::values.debug_pad_buttons.end(), buttons.begin(), - Input::CreateDevice<Input::ButtonDevice>); + Settings::values.debug_pad_buttons.begin() + + Settings::NativeButton::NUM_BUTTONS_HID, + buttons.begin(), Input::CreateDevice<Input::ButtonDevice>); std::transform(Settings::values.debug_pad_analogs.begin(), Settings::values.debug_pad_analogs.end(), analogs.begin(), Input::CreateDevice<Input::AnalogDevice>); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 7a88ae029..792d26e52 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -5,6 +5,8 @@ #include <cstring> #include "common/assert.h" #include "common/logging/log.h" +#include "core/core_timing.h" +#include "core/core_timing_util.h" #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" namespace Service::Nvidia::Devices { @@ -33,6 +35,8 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec return ZBCQueryTable(input, output); case IoctlCommand::IocFlushL2: return FlushL2(input, output); + case IoctlCommand::IocGetGpuTime: + return GetGpuTime(input, output); } UNIMPLEMENTED_MSG("Unimplemented ioctl"); return 0; @@ -169,4 +173,13 @@ u32 nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& outp return 0; } +u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { + LOG_DEBUG(Service_NVDRV, "called"); + IoctlGetGpuTime params{}; + std::memcpy(¶ms, input.data(), input.size()); + params.gpu_time = CoreTiming::cyclesToNs(CoreTiming::GetTicks()); + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 3bbf028ad..240435eea 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -156,6 +156,11 @@ private: }; static_assert(sizeof(IoctlFlushL2) == 8, "IoctlFlushL2 is incorrect size"); + struct IoctlGetGpuTime { + u64_le gpu_time; + }; + static_assert(sizeof(IoctlGetGpuTime) == 8, "IoctlGetGpuTime is incorrect size"); + u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output); u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output); u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); @@ -164,6 +169,7 @@ private: u32 ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); u32 ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); u32 FlushL2(const std::vector<u8>& input, std::vector<u8>& output); + u32 GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index ac3859353..602086eed 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -88,6 +88,20 @@ void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NVDRV, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { + // According to SwitchBrew, this has no inputs and no outputs, so effectively does nothing on + // retail hardware. + LOG_DEBUG(Service_NVDRV, "called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) : ServiceFramework(name), nvdrv(std::move(nvdrv)) { static const FunctionInfo functions[] = { @@ -97,10 +111,10 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) {3, &NVDRV::Initialize, "Initialize"}, {4, &NVDRV::QueryEvent, "QueryEvent"}, {5, nullptr, "MapSharedMem"}, - {6, nullptr, "GetStatus"}, + {6, &NVDRV::GetStatus, "GetStatus"}, {7, nullptr, "ForceSetClientPID"}, {8, &NVDRV::SetClientPID, "SetClientPID"}, - {9, nullptr, "DumpGraphicsMemoryInfo"}, + {9, &NVDRV::DumpGraphicsMemoryInfo, "DumpGraphicsMemoryInfo"}, {10, nullptr, "InitializeDevtools"}, {11, &NVDRV::Ioctl, "Ioctl2"}, {12, nullptr, "Ioctl3"}, diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index d340893c2..5a1e4baa7 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h @@ -24,6 +24,8 @@ private: void QueryEvent(Kernel::HLERequestContext& ctx); void SetClientPID(Kernel::HLERequestContext& ctx); void FinishInitialize(Kernel::HLERequestContext& ctx); + void GetStatus(Kernel::HLERequestContext& ctx); + void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx); std::shared_ptr<Module> nvdrv; diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 464e79d01..9ca8483a5 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -63,6 +63,17 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)); } +ResultCode ServiceManager::UnregisterService(const std::string& name) { + CASCADE_CODE(ValidateServiceName(name)); + + const auto iter = registered_services.find(name); + if (iter == registered_services.end()) + return ERR_SERVICE_NOT_REGISTERED; + + registered_services.erase(iter); + return RESULT_SUCCESS; +} + ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> ServiceManager::GetServicePort( const std::string& name) { @@ -127,13 +138,52 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { } } +void SM::RegisterService(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto name_buf = rp.PopRaw<std::array<char, 8>>(); + const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); + + const std::string name(name_buf.begin(), end); + + const auto unk_bool = static_cast<bool>(rp.PopRaw<u32>()); + const auto session_count = rp.PopRaw<u32>(); + + LOG_DEBUG(Service_SM, "called with unk_bool={}", unk_bool); + + auto handle = service_manager->RegisterService(name, session_count); + if (handle.Failed()) { + LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", + handle.Code().raw); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(handle.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; + rb.Push(handle.Code()); + rb.PushMoveObjects(std::move(handle).Unwrap()); +} + +void SM::UnregisterService(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto name_buf = rp.PopRaw<std::array<char, 8>>(); + const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); + + const std::string name(name_buf.begin(), end); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(service_manager->UnregisterService(name)); +} + SM::SM(std::shared_ptr<ServiceManager> service_manager) : ServiceFramework("sm:", 4), service_manager(std::move(service_manager)) { static const FunctionInfo functions[] = { {0x00000000, &SM::Initialize, "Initialize"}, {0x00000001, &SM::GetService, "GetService"}, - {0x00000002, nullptr, "RegisterService"}, - {0x00000003, nullptr, "UnregisterService"}, + {0x00000002, &SM::RegisterService, "RegisterService"}, + {0x00000003, &SM::UnregisterService, "UnregisterService"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 4f8145dda..bef25433e 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -35,6 +35,8 @@ public: private: void Initialize(Kernel::HLERequestContext& ctx); void GetService(Kernel::HLERequestContext& ctx); + void RegisterService(Kernel::HLERequestContext& ctx); + void UnregisterService(Kernel::HLERequestContext& ctx); std::shared_ptr<ServiceManager> service_manager; }; @@ -48,6 +50,7 @@ public: ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name, unsigned int max_sessions); + ResultCode UnregisterService(const std::string& name); ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name); ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ConnectToService(const std::string& name); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index d25fdb1fe..a72416084 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -510,7 +510,11 @@ private: if (transaction == TransactionId::Connect) { IGBPConnectRequestParcel request{ctx.ReadBuffer()}; - IGBPConnectResponseParcel response{1280, 720}; + IGBPConnectResponseParcel response{ + static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) * + Settings::values.resolution_factor), + static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) * + Settings::values.resolution_factor)}; ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::SetPreallocatedBuffer) { IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()}; @@ -692,11 +696,15 @@ private: rb.Push(RESULT_SUCCESS); if (Settings::values.use_docked_mode) { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * + static_cast<u32>(Settings::values.resolution_factor)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * + static_cast<u32>(Settings::values.resolution_factor)); } else { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * + static_cast<u32>(Settings::values.resolution_factor)); + rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * + static_cast<u32>(Settings::values.resolution_factor)); } rb.PushRaw<float>(60.0f); @@ -901,11 +909,15 @@ private: rb.Push(RESULT_SUCCESS); if (Settings::values.use_docked_mode) { - rb.Push(static_cast<u64>(DisplayResolution::DockedWidth)); - rb.Push(static_cast<u64>(DisplayResolution::DockedHeight)); + rb.Push(static_cast<u64>(DisplayResolution::DockedWidth) * + static_cast<u32>(Settings::values.resolution_factor)); + rb.Push(static_cast<u64>(DisplayResolution::DockedHeight) * + static_cast<u32>(Settings::values.resolution_factor)); } else { - rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth)); - rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); + rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) * + static_cast<u32>(Settings::values.resolution_factor)); + rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) * + static_cast<u32>(Settings::values.resolution_factor)); } } @@ -922,6 +934,8 @@ private: void ListDisplays(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; DisplayInfo display_info; + display_info.width *= static_cast<u64>(Settings::values.resolution_factor); + display_info.height *= static_cast<u64>(Settings::values.resolution_factor); ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); |
