diff options
Diffstat (limited to 'src/core/hle/service')
46 files changed, 1200 insertions, 163 deletions
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index ee7d07aa7..52c3491d5 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -65,12 +65,19 @@ void ACC_U0::GetUserExistence(Kernel::HLERequestContext& ctx) { } void ACC_U0::ListAllUsers(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID}; - const auto& output_buffer = ctx.BufferDescriptorC()[0]; - Memory::WriteBlock(output_buffer.Address(), user_ids.data(), user_ids.size()); + ctx.WriteBuffer(user_ids.data(), user_ids.size()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void ACC_U0::ListOpenUsers(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID}; + ctx.WriteBuffer(user_ids.data(), user_ids.size()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_DEBUG(Service_ACC, "called"); } void ACC_U0::GetProfile(Kernel::HLERequestContext& ctx) { @@ -104,6 +111,7 @@ ACC_U0::ACC_U0() : ServiceFramework("acc:u0") { static const FunctionInfo functions[] = { {1, &ACC_U0::GetUserExistence, "GetUserExistence"}, {2, &ACC_U0::ListAllUsers, "ListAllUsers"}, + {3, &ACC_U0::ListOpenUsers, "ListOpenUsers"}, {4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"}, {5, &ACC_U0::GetProfile, "GetProfile"}, {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h index d7732e75b..222f37282 100644 --- a/src/core/hle/service/acc/acc_u0.h +++ b/src/core/hle/service/acc/acc_u0.h @@ -29,6 +29,7 @@ public: private: void GetUserExistence(Kernel::HLERequestContext& ctx); void ListAllUsers(Kernel::HLERequestContext& ctx); + void ListOpenUsers(Kernel::HLERequestContext& ctx); void GetLastOpenedUser(Kernel::HLERequestContext& ctx); void GetProfile(Kernel::HLERequestContext& ctx); void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 07cea8717..d9f003ed4 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -2,12 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <cinttypes> +#include "core/file_sys/filesystem.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/event.h" #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/apm/apm.h" +#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/nvflinger/nvflinger.h" namespace Service { @@ -34,7 +37,38 @@ void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) rb.Push(RESULT_SUCCESS); } -IAudioController::IAudioController() : ServiceFramework("IAudioController") {} +IAudioController::IAudioController() : ServiceFramework("IAudioController") { + static const FunctionInfo functions[] = { + {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, + {1, &IAudioController::GetMainAppletExpectedMasterVolume, + "GetMainAppletExpectedMasterVolume"}, + {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, + "GetLibraryAppletExpectedMasterVolume"}, + {3, nullptr, "ChangeMainAppletMasterVolume"}, + {4, nullptr, "SetTransparentVolumeRate"}, + }; + RegisterHandlers(functions); +} + +void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(volume); +} + +void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(volume); +} IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {} @@ -46,6 +80,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger {1, &ISelfController::LockExit, "LockExit"}, {2, &ISelfController::UnlockExit, "UnlockExit"}, {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, + {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, {12, &ISelfController::SetPerformanceModeChangedNotification, @@ -98,6 +133,13 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag)); } +void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_AM, "(STUBBED) called"); +} + void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -306,11 +348,11 @@ private: u64 offset = rp.Pop<u64>(); - const auto& output_buffer = ctx.BufferDescriptorC()[0]; + const size_t size{ctx.GetWriteBufferSize()}; - ASSERT(offset + output_buffer.Size() <= buffer.size()); + ASSERT(offset + size <= buffer.size()); - Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size()); + ctx.WriteBuffer(buffer.data() + offset, size); IPC::ResponseBuilder rb{ctx, 2}; @@ -377,9 +419,25 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { } void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); + IPC::RequestParser rp{ctx}; + u128 uid = rp.PopRaw<u128>(); + + LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); + + IPC::ResponseBuilder rb{ctx, 4}; + + FileSys::Path unused; + auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused); + if (savedata.Failed()) { + // Create the save data and return an error indicating that the operation was performed. + FileSystem::FormatFileSystem(FileSystem::Type::SaveData); + // TODO(Subv): Find out the correct error code for this. + rb.Push(ResultCode(ErrorModule::FS, 40)); + } else { + rb.Push(RESULT_SUCCESS); + } + + rb.Push<u64>(0); } void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 793ac6555..27dbd8c95 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -36,6 +36,13 @@ private: class IAudioController final : public ServiceFramework<IAudioController> { public: IAudioController(); + +private: + void SetExpectedMasterVolume(Kernel::HLERequestContext& ctx); + void GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx); + void GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx); + + u32 volume{100}; }; class IDisplayController final : public ServiceFramework<IDisplayController> { @@ -62,6 +69,7 @@ private: void UnlockExit(Kernel::HLERequestContext& ctx); void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); + void SetScreenShotPermission(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; Kernel::SharedPtr<Kernel::Event> launchable_event; diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 260683201..8b55d2fcb 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -2,16 +2,44 @@ // 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/aoc/aoc_u.h" namespace Service { namespace AOC { +AOC_U::AOC_U() : ServiceFramework("aoc:u") { + static const FunctionInfo functions[] = { + {0, nullptr, "CountAddOnContentByApplicationId"}, + {1, nullptr, "ListAddOnContentByApplicationId"}, + {2, &AOC_U::CountAddOnContent, "CountAddOnContent"}, + {3, &AOC_U::ListAddOnContent, "ListAddOnContent"}, + {4, nullptr, "GetAddOnContentBaseIdByApplicationId"}, + {5, nullptr, "GetAddOnContentBaseId"}, + {6, nullptr, "PrepareAddOnContentByApplicationId"}, + {7, nullptr, "PrepareAddOnContent"}, + }; + RegisterHandlers(functions); +} + +void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push<u64>(0); + LOG_WARNING(Service_AOC, "(STUBBED) called"); +} + +void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push<u64>(0); + LOG_WARNING(Service_AOC, "(STUBBED) called"); +} + void InstallInterfaces(SM::ServiceManager& service_manager) { std::make_shared<AOC_U>()->InstallAsService(service_manager); } -AOC_U::AOC_U() : ServiceFramework("aoc:u") {} - } // namespace AOC } // namespace Service diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h index 0cbbf1e5d..6e0ba15a5 100644 --- a/src/core/hle/service/aoc/aoc_u.h +++ b/src/core/hle/service/aoc/aoc_u.h @@ -13,6 +13,10 @@ class AOC_U final : public ServiceFramework<AOC_U> { public: AOC_U(); ~AOC_U() = default; + +private: + void CountAddOnContent(Kernel::HLERequestContext& ctx); + void ListAddOnContent(Kernel::HLERequestContext& ctx); }; /// Registers all AOC services with the specified service manager. diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index f56ba2ea1..e873d768f 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -52,7 +52,9 @@ public: CoreTiming::ScheduleEvent(audio_ticks, audio_event); } - ~IAudioOut() = default; + ~IAudioOut() { + CoreTiming::UnscheduleEvent(audio_event, 0); + } private: void StartAudioOut(Kernel::HLERequestContext& ctx) { @@ -99,8 +101,6 @@ private: void GetReleasedAudioOutBuffer_1(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); - const auto& buffer = ctx.BufferDescriptorB()[0]; - // TODO(st4rk): This is how libtransistor currently implements the // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address // is used to know which buffer should be filled with data and send again to the service @@ -112,7 +112,7 @@ private: queue_keys.pop_back(); } - Memory::WriteBlock(buffer.Address(), &key, sizeof(u64)); + ctx.WriteBuffer(&key, sizeof(u64)); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); @@ -158,10 +158,8 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); IPC::RequestParser rp{ctx}; - auto& buffer = ctx.BufferDescriptorB()[0]; const std::string audio_interface = "AudioInterface"; - - Memory::WriteBlock(buffer.Address(), &audio_interface[0], audio_interface.size()); + ctx.WriteBuffer(audio_interface.c_str(), audio_interface.size()); IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index c8d8ba748..1cbca6c4b 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -45,7 +45,9 @@ public: // Start the audio event CoreTiming::ScheduleEvent(audio_ticks, audio_event); } - ~IAudioRenderer() = default; + ~IAudioRenderer() { + CoreTiming::UnscheduleEvent(audio_event, 0); + } private: void UpdateAudioCallback() { @@ -53,7 +55,8 @@ private: } void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) { - AudioRendererResponseData response_data = {0}; + LOG_DEBUG(Service_Audio, "%s", ctx.Description().c_str()); + AudioRendererResponseData response_data{}; response_data.section_0_size = response_data.state_entries.size() * sizeof(AudioRendererStateEntry); @@ -69,9 +72,7 @@ private: response_data.state_entries[i].state = 5; } - auto& buffer = ctx.BufferDescriptorB()[0]; - - Memory::WriteBlock(buffer.Address(), &response_data, response_data.total_size); + ctx.WriteBuffer(&response_data, response_data.total_size); IPC::ResponseBuilder rb{ctx, 2}; @@ -179,10 +180,10 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { } void AudRenU::GetAudioRenderersProcessMasterVolume(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - + rb.Push<u32>(100); LOG_WARNING(Service_Audio, "(STUBBED) called"); } diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 4b47548fd..ef05955b9 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -3,7 +3,9 @@ // Refer to the license.txt file included. #include <boost/container/flat_map.hpp> +#include "common/file_util.h" #include "core/file_sys/filesystem.h" +#include "core/file_sys/savedata_factory.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" @@ -41,12 +43,30 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, return itr->second->Open(path); } -void UnregisterFileSystems() { +ResultCode FormatFileSystem(Type type) { + LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type); + + auto itr = filesystem_map.find(type); + if (itr == filesystem_map.end()) { + // TODO(bunnei): Find a better error code for this + return ResultCode(-1); + } + + FileSys::Path unused; + return itr->second->Format(unused); +} + +void RegisterFileSystems() { filesystem_map.clear(); + + std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); + + auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory)); + RegisterFileSystem(std::move(savedata), Type::SaveData); } void InstallInterfaces(SM::ServiceManager& service_manager) { - UnregisterFileSystems(); + RegisterFileSystems(); std::make_shared<FSP_SRV>()->InstallAsService(service_manager); } diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index a674c9493..8d30e94a1 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -25,6 +25,7 @@ namespace FileSystem { /// Supported FileSystem types enum class Type { RomFS = 1, + SaveData = 2, }; /** @@ -43,6 +44,13 @@ ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& fact ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, FileSys::Path& path); +/** + * Formats a file system + * @param type Type of the file system to format + * @return ResultCode of the operation + */ +ResultCode FormatFileSystem(Type type); + /// Registers all Filesystem services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 34d4fd035..97b3fa290 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <cinttypes> #include "common/logging/log.h" #include "core/core.h" #include "core/file_sys/filesystem.h" @@ -33,12 +34,10 @@ private: IPC::RequestParser rp{ctx}; const s64 offset = rp.Pop<s64>(); const s64 length = rp.Pop<s64>(); - const auto& descriptor = ctx.BufferDescriptorB()[0]; LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length); // Error checking - ASSERT_MSG(length == descriptor.Size(), "unexpected size difference"); if (length < 0) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); @@ -60,17 +59,194 @@ private: } // Write the data to memory - Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size()); + ctx.WriteBuffer(output); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } }; +class IFile final : public ServiceFramework<IFile> { +public: + explicit IFile(std::unique_ptr<FileSys::StorageBackend>&& backend) + : ServiceFramework("IFile"), backend(std::move(backend)) { + static const FunctionInfo functions[] = { + {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, nullptr, "Flush"}, + {3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, + }; + RegisterHandlers(functions); + } + +private: + std::unique_ptr<FileSys::StorageBackend> backend; + + void Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 unk = rp.Pop<u64>(); + const s64 offset = rp.Pop<s64>(); + const s64 length = rp.Pop<s64>(); + + LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length); + + // Error checking + if (length < 0) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); + return; + } + if (offset < 0) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset)); + return; + } + + // Read the data from the Storage backend + std::vector<u8> output(length); + ResultVal<size_t> res = backend->Read(offset, length, output.data()); + if (res.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + return; + } + + // Write the data to memory + ctx.WriteBuffer(output); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast<u64>(*res)); + } + + void Write(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 unk = rp.Pop<u64>(); + const s64 offset = rp.Pop<s64>(); + const s64 length = rp.Pop<s64>(); + + LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length); + + // Error checking + if (length < 0) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); + return; + } + if (offset < 0) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset)); + return; + } + + // Write the data to the Storage backend + std::vector<u8> data = ctx.ReadBuffer(); + ResultVal<size_t> res = backend->Write(offset, length, true, data.data()); + if (res.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } +}; + +class IFileSystem final : public ServiceFramework<IFileSystem> { +public: + explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend) + : ServiceFramework("IFileSystem"), backend(std::move(backend)) { + static const FunctionInfo functions[] = { + {0, &IFileSystem::CreateFile, "CreateFile"}, + {7, &IFileSystem::GetEntryType, "GetEntryType"}, + {8, &IFileSystem::OpenFile, "OpenFile"}, + {10, &IFileSystem::Commit, "Commit"}, + }; + RegisterHandlers(functions); + } + + void CreateFile(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto file_buffer = ctx.ReadBuffer(); + auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); + + std::string name(file_buffer.begin(), end); + + u64 mode = rp.Pop<u64>(); + u32 size = rp.Pop<u32>(); + + LOG_DEBUG(Service_FS, "called file %s mode 0x%" PRIX64 " size 0x%08X", name.c_str(), mode, + size); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(backend->CreateFile(name, size)); + } + + void OpenFile(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto file_buffer = ctx.ReadBuffer(); + auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); + + std::string name(file_buffer.begin(), end); + + auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>()); + + LOG_DEBUG(Service_FS, "called file %s mode %u", name.c_str(), static_cast<u32>(mode)); + + auto result = backend->OpenFile(name, mode); + if (result.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result.Code()); + return; + } + + auto file = std::move(result.Unwrap()); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IFile>(std::move(file)); + } + + void GetEntryType(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto file_buffer = ctx.ReadBuffer(); + auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); + + std::string name(file_buffer.begin(), end); + + LOG_DEBUG(Service_FS, "called file %s", name.c_str()); + + auto result = backend->GetEntryType(name); + if (result.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(static_cast<u32>(*result)); + } + + void Commit(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + +private: + std::unique_ptr<FileSys::FileSystemBackend> backend; +}; + FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { static const FunctionInfo functions[] = { {1, &FSP_SRV::Initalize, "Initalize"}, {18, &FSP_SRV::MountSdCard, "MountSdCard"}, + {22, &FSP_SRV::CreateSaveData, "CreateSaveData"}, + {51, &FSP_SRV::MountSaveData, "MountSaveData"}, {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, {202, nullptr, "OpenDataStorageByDataId"}, {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, @@ -104,6 +280,30 @@ void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto save_struct = rp.PopRaw<std::array<u8, 0x40>>(); + auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>(); + u128 uid = rp.PopRaw<u128>(); + + LOG_WARNING(Service_FS, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + + FileSys::Path unused; + auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap(); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IFileSystem>(std::move(filesystem)); +} + void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 56afc4b90..e15ba4375 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -24,6 +24,8 @@ private: void Initalize(Kernel::HLERequestContext& ctx); void MountSdCard(Kernel::HLERequestContext& ctx); + void CreateSaveData(Kernel::HLERequestContext& ctx); + void MountSaveData(Kernel::HLERequestContext& ctx); void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); void OpenRomStorage(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp new file mode 100644 index 000000000..26593bb0c --- /dev/null +++ b/src/core/hle/service/friend/friend.cpp @@ -0,0 +1,28 @@ +// Copyright 2018 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/friend/friend.h" +#include "core/hle/service/friend/friend_a.h" + +namespace Service { +namespace Friend { + +void Module::Interface::Unknown(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_Friend, "(STUBBED) called"); +} + +Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) + : ServiceFramework(name), module(std::move(module)) {} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + auto module = std::make_shared<Module>(); + std::make_shared<Friend_A>(module)->InstallAsService(service_manager); +} + +} // namespace Friend +} // namespace Service diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h new file mode 100644 index 000000000..ffa498397 --- /dev/null +++ b/src/core/hle/service/friend/friend.h @@ -0,0 +1,29 @@ +// 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/service.h" + +namespace Service { +namespace Friend { + +class Module final { +public: + class Interface : public ServiceFramework<Interface> { + public: + Interface(std::shared_ptr<Module> module, const char* name); + + void Unknown(Kernel::HLERequestContext& ctx); + + protected: + std::shared_ptr<Module> module; + }; +}; + +/// Registers all Friend services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Friend +} // namespace Service diff --git a/src/core/hle/service/friend/friend_a.cpp b/src/core/hle/service/friend/friend_a.cpp new file mode 100644 index 000000000..e1f2397c2 --- /dev/null +++ b/src/core/hle/service/friend/friend_a.cpp @@ -0,0 +1,19 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/friend/friend_a.h" + +namespace Service { +namespace Friend { + +Friend_A::Friend_A(std::shared_ptr<Module> module) + : Module::Interface(std::move(module), "friend:a") { + static const FunctionInfo functions[] = { + {0, &Friend_A::Unknown, "Unknown"}, + }; + RegisterHandlers(functions); +} + +} // namespace Friend +} // namespace Service diff --git a/src/core/hle/service/friend/friend_a.h b/src/core/hle/service/friend/friend_a.h new file mode 100644 index 000000000..68fa58297 --- /dev/null +++ b/src/core/hle/service/friend/friend_a.h @@ -0,0 +1,18 @@ +// 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/friend/friend.h" + +namespace Service { +namespace Friend { + +class Friend_A final : public Module::Interface { +public: + explicit Friend_A(std::shared_ptr<Module> module); +}; + +} // namespace Friend +} // namespace Service diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index d757d2eae..7e04ad8d4 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -45,6 +45,10 @@ public: CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); } + ~IAppletResource() { + CoreTiming::UnscheduleEvent(pad_update_event, 0); + } + private: void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -176,7 +180,10 @@ public: {0, &Hid::CreateAppletResource, "CreateAppletResource"}, {1, &Hid::ActivateDebugPad, "ActivateDebugPad"}, {11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"}, + {21, &Hid::ActivateMouse, "ActivateMouse"}, + {31, &Hid::ActivateKeyboard, "ActivateKeyboard"}, {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"}, + {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"}, {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"}, {103, &Hid::ActivateNpad, "ActivateNpad"}, @@ -184,9 +191,15 @@ public: "AcquireNpadStyleSetUpdateEventHandle"}, {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, + {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, + "SetNpadJoyAssignmentModeSingleByDefault"}, {124, nullptr, "SetNpadJoyAssignmentModeDual"}, {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, + {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, + {201, &Hid::SendVibrationValue, "SendVibrationValue"}, + {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"}, {203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"}, + {206, &Hid::SendVibrationValues, "SendVibrationValues"}, }; RegisterHandlers(functions); @@ -222,12 +235,30 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void ActivateMouse(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + + void ActivateKeyboard(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); } + void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -266,18 +297,49 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + + void SendVibrationValue(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + + void GetActualVibrationValue(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); } + void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push<u64>(0); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<IActiveVibrationDeviceList>(); LOG_DEBUG(Service_HID, "called"); } + + void SendVibrationValues(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } }; void ReloadInputDevices() {} diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 290a2ee74..e6f05eae5 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/event.h" #include "core/hle/service/nifm/nifm.h" #include "core/hle/service/nifm/nifm_a.h" #include "core/hle/service/nifm/nifm_s.h" @@ -28,9 +29,9 @@ class IRequest final : public ServiceFramework<IRequest> { public: explicit IRequest() : ServiceFramework("IRequest") { static const FunctionInfo functions[] = { - {0, nullptr, "GetRequestState"}, - {1, nullptr, "GetResult"}, - {2, nullptr, "GetSystemEventReadableHandles"}, + {0, &IRequest::GetRequestState, "GetRequestState"}, + {1, &IRequest::GetResult, "GetResult"}, + {2, &IRequest::GetSystemEventReadableHandles, "GetSystemEventReadableHandles"}, {3, nullptr, "Cancel"}, {4, nullptr, "Submit"}, {5, nullptr, "SetRequirement"}, @@ -55,7 +56,32 @@ public: {25, nullptr, "UnregisterSocketDescriptor"}, }; RegisterHandlers(functions); + + event1 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event1"); + event2 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event2"); + } + +private: + void GetRequestState(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); } + void GetResult(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); + } + void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2, 2}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(event1, event2); + } + + Kernel::SharedPtr<Kernel::Event> event1, event2; }; class INetworkProfile final : public ServiceFramework<INetworkProfile> { diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp new file mode 100644 index 000000000..45681c50f --- /dev/null +++ b/src/core/hle/service/ns/ns.cpp @@ -0,0 +1,16 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/ns/ns.h" +#include "core/hle/service/ns/pl_u.h" + +namespace Service { +namespace NS { + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared<PL_U>()->InstallAsService(service_manager); +} + +} // namespace NS +} // namespace Service diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h new file mode 100644 index 000000000..a4b7e3ded --- /dev/null +++ b/src/core/hle/service/ns/ns.h @@ -0,0 +1,16 @@ +// 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/service.h" + +namespace Service { +namespace NS { + +/// Registers all NS services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace NS +} // namespace Service diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp new file mode 100644 index 000000000..cc9d03a7c --- /dev/null +++ b/src/core/hle/service/ns/pl_u.cpp @@ -0,0 +1,111 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_paths.h" +#include "common/file_util.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ns/pl_u.h" + +namespace Service { +namespace NS { + +struct FontRegion { + u32 offset; + u32 size; +}; + +// The below data is specific to shared font data dumped from Switch on f/w 2.2 +// Virtual address and offsets/sizes likely will vary by dump +static constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL}; +static constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000}; +static constexpr std::array<FontRegion, 6> SHARED_FONT_REGIONS{ + FontRegion{0x00000008, 0x001fe764}, FontRegion{0x001fe774, 0x00773e58}, + FontRegion{0x009725d4, 0x0001aca8}, FontRegion{0x0098d284, 0x00369cec}, + FontRegion{0x00cf6f78, 0x0039b858}, FontRegion{0x010927d8, 0x00019e80}, +}; + +enum class LoadState : u32 { + Loading = 0, + Done = 1, +}; + +PL_U::PL_U() : ServiceFramework("pl:u") { + static const FunctionInfo functions[] = { + {1, &PL_U::GetLoadState, "GetLoadState"}, + {2, &PL_U::GetSize, "GetSize"}, + {3, &PL_U::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, + {4, &PL_U::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}}; + RegisterHandlers(functions); + + // Attempt to load shared font data from disk + const std::string filepath{FileUtil::GetUserPath(D_SYSDATA_IDX) + SHARED_FONT}; + FileUtil::CreateFullPath(filepath); // Create path if not already created + FileUtil::IOFile file(filepath, "rb"); + + if (file.IsOpen()) { + // Read shared font data + ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE); + shared_font = std::make_shared<std::vector<u8>>(static_cast<size_t>(file.GetSize())); + file.ReadBytes(shared_font->data(), shared_font->size()); + } else { + LOG_WARNING(Service_NS, "Unable to load shared font: %s", filepath.c_str()); + } +} + +void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 font_id{rp.Pop<u32>()}; + + LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(static_cast<u32>(LoadState::Done)); +} + +void PL_U::GetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 font_id{rp.Pop<u32>()}; + + LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size); +} + +void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 font_id{rp.Pop<u32>()}; + + LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset); +} + +void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { + if (shared_font != nullptr) { + // TODO(bunnei): This is a less-than-ideal solution to load a RAM dump of the Switch shared + // font data. This (likely) relies on exact address, size, and offsets from the original + // dump. In the future, we need to replace this with a more robust solution. + + // Map backing memory for the font data + Kernel::g_current_process->vm_manager.MapMemoryBlock(SHARED_FONT_MEM_VADDR, shared_font, 0, + SHARED_FONT_MEM_SIZE, + Kernel::MemoryState::Shared); + + // Create shared font memory object + shared_font_mem = Kernel::SharedMemory::Create( + Kernel::g_current_process, SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite, + Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE, + "PL_U:shared_font_mem"); + } + + LOG_DEBUG(Service_NS, "called"); + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(shared_font_mem); +} + +} // namespace NS +} // namespace Service diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h new file mode 100644 index 000000000..7a4766338 --- /dev/null +++ b/src/core/hle/service/ns/pl_u.h @@ -0,0 +1,33 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include "core/hle/kernel/shared_memory.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace NS { + +class PL_U final : public ServiceFramework<PL_U> { +public: + PL_U(); + ~PL_U() = default; + +private: + void GetLoadState(Kernel::HLERequestContext& ctx); + void GetSize(Kernel::HLERequestContext& ctx); + void GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx); + void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); + + /// Handle to shared memory region designated for a shared font + Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem; + + /// Backing memory for the shared font data + std::shared_ptr<std::vector<u8>> shared_font; +}; + +} // namespace NS +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index ee99ab280..45711d686 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -17,6 +17,8 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector< switch (static_cast<IoctlCommand>(command.raw)) { case IoctlCommand::IocGetConfigCommand: return NvOsGetConfigU32(input, output); + case IoctlCommand::IocCtrlEventWaitCommand: + return IocCtrlEventWait(input, output); } UNIMPLEMENTED(); return 0; @@ -45,6 +47,18 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& return 0; } +u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) { + IocCtrlEventWaitParams params{}; + std::memcpy(¶ms, input.data(), sizeof(params)); + LOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id=%u threshold=%u timeout=%d", + params.syncpt_id, params.threshold, params.timeout); + + // TODO(Subv): Implement actual syncpt waiting. + params.value = 0; + std::memcpy(output.data(), ¶ms, sizeof(params)); + return 0; +} + } // namespace Devices } // namespace Nvidia } // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index fd02a5e45..0ca01aa6d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -31,6 +31,7 @@ private: IocModuleRegRDWRCommand = 0xC008010E, IocSyncptWaitexCommand = 0xC0100019, IocSyncptReadMaxCommand = 0xC008001A, + IocCtrlEventWaitCommand = 0xC010001D, IocGetConfigCommand = 0xC183001B, }; @@ -41,7 +42,17 @@ private: }; static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size"); + struct IocCtrlEventWaitParams { + u32_le syncpt_id; + u32_le threshold; + s32_le timeout; + u32_le value; + }; + static_assert(sizeof(IocCtrlEventWaitParams) == 16, "IocCtrlEventWaitParams is incorrect size"); + u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); + + u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output); }; } // namespace Devices diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index cd8c0c605..b3842eb4c 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -103,11 +103,8 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { [&](const auto& entry) { return entry.second->id == params.id; }); ASSERT(itr != handles.end()); - // Make a new handle for the object - u32 handle = next_handle++; - handles[handle] = itr->second; - - params.handle = handle; + // Return the existing handle instead of creating a new one. + params.handle = itr->first; std::memcpy(output.data(), ¶ms, sizeof(params)); return 0; diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 1a5efaeaf..c70370f1f 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -15,9 +15,8 @@ namespace Nvidia { void NVDRV::Open(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); - auto buffer = ctx.BufferDescriptorA()[0]; - - std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); + const auto& buffer = ctx.ReadBuffer(); + std::string device_name(buffer.begin(), buffer.end()); u32 fd = nvdrv->Open(device_name); IPC::ResponseBuilder rb{ctx, 4}; @@ -33,25 +32,13 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { u32 fd = rp.Pop<u32>(); u32 command = rp.Pop<u32>(); + std::vector<u8> output(ctx.GetWriteBufferSize()); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - if (ctx.BufferDescriptorA()[0].Size() != 0) { - auto input_buffer = ctx.BufferDescriptorA()[0]; - auto output_buffer = ctx.BufferDescriptorB()[0]; - std::vector<u8> input(input_buffer.Size()); - std::vector<u8> output(output_buffer.Size()); - Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); - rb.Push(nvdrv->Ioctl(fd, command, input, output)); - Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); - } else { - auto input_buffer = ctx.BufferDescriptorX()[0]; - auto output_buffer = ctx.BufferDescriptorC()[0]; - std::vector<u8> input(input_buffer.size); - std::vector<u8> output(output_buffer.size); - Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.size); - rb.Push(nvdrv->Ioctl(fd, command, input, output)); - Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.size); - } + rb.Push(nvdrv->Ioctl(fd, command, ctx.ReadBuffer(), output)); + + ctx.WriteBuffer(output); } void NVDRV::Close(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index e44644624..6a55ff96d 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -17,6 +17,13 @@ namespace Devices { class nvdevice; } +struct IoctlFence { + u32 id; + u32 value; +}; + +static_assert(sizeof(IoctlFence) == 8, "IoctlFence has wrong size"); + class Module final { public: Module(); diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 2089462b7..0d30f54dc 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -6,6 +6,7 @@ #include "common/alignment.h" #include "common/scope_exit.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" #include "core/hle/service/nvdrv/nvdrv.h" @@ -129,6 +130,7 @@ void NVFlinger::Compose() { if (buffer == boost::none) { // There was no queued buffer to draw, render previous frame + Core::System::GetInstance().perf_stats.EndGameFrame(); VideoCore::g_renderer->SwapBuffers({}); continue; } @@ -148,6 +150,9 @@ void NVFlinger::Compose() { igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform); buffer_queue->ReleaseBuffer(buffer->slot); + + // TODO(Subv): Figure out when we should actually signal this event. + buffer_queue->GetNativeHandle()->Signal(); } } diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 1dd04a12f..78380475c 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -20,13 +20,15 @@ #include "core/hle/service/apm/apm.h" #include "core/hle/service/audio/audio.h" #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/friend/friend.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/lm/lm.h" #include "core/hle/service/nifm/nifm.h" +#include "core/hle/service/ns/ns.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/pctl/pctl.h" #include "core/hle/service/service.h" -#include "core/hle/service/set/set.h" +#include "core/hle/service/set/settings.h" #include "core/hle/service/sm/controller.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/sockets/sockets.h" @@ -179,9 +181,11 @@ void Init() { APM::InstallInterfaces(*SM::g_service_manager); Audio::InstallInterfaces(*SM::g_service_manager); FileSystem::InstallInterfaces(*SM::g_service_manager); + Friend::InstallInterfaces(*SM::g_service_manager); HID::InstallInterfaces(*SM::g_service_manager); LM::InstallInterfaces(*SM::g_service_manager); NIFM::InstallInterfaces(*SM::g_service_manager); + NS::InstallInterfaces(*SM::g_service_manager); Nvidia::InstallInterfaces(*SM::g_service_manager); PCTL::InstallInterfaces(*SM::g_service_manager); Sockets::InstallInterfaces(*SM::g_service_manager); diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 1062ba8b3..aa7c924e7 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -17,9 +17,7 @@ void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { u32 id = rp.Pop<u32>(); constexpr std::array<u8, 13> lang_codes{}; - const auto& output_buffer = ctx.BufferDescriptorC()[0]; - - Memory::WriteBlock(output_buffer.Address(), lang_codes.data(), lang_codes.size()); + ctx.WriteBuffer(lang_codes.data(), lang_codes.size()); IPC::ResponseBuilder rb{ctx, 2}; @@ -28,16 +26,19 @@ void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_SET, "(STUBBED) called"); } -SET::SET(const char* name) : ServiceFramework(name) { +SET::SET() : ServiceFramework("set") { static const FunctionInfo functions[] = { + {0, nullptr, "GetLanguageCode"}, {1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"}, + {2, nullptr, "MakeLanguageCode"}, + {3, nullptr, "GetAvailableLanguageCodeCount"}, + {4, nullptr, "GetRegionCode"}, + {5, nullptr, "GetAvailableLanguageCodes2"}, + {6, nullptr, "GetAvailableLanguageCodeCount2"}, + {7, nullptr, "GetKeyCodeMap"}, }; RegisterHandlers(functions); } -void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<SET>("set")->InstallAsService(service_manager); -} - } // namespace Set } // namespace Service diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h index 61e957946..7b7814ed1 100644 --- a/src/core/hle/service/set/set.h +++ b/src/core/hle/service/set/set.h @@ -11,15 +11,12 @@ namespace Set { class SET final : public ServiceFramework<SET> { public: - explicit SET(const char* name); + explicit SET(); ~SET() = default; private: void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx); }; -/// Registers all Set services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); - } // namespace Set } // namespace Service diff --git a/src/core/hle/service/set/set_cal.cpp b/src/core/hle/service/set/set_cal.cpp new file mode 100644 index 000000000..6231acd96 --- /dev/null +++ b/src/core/hle/service/set/set_cal.cpp @@ -0,0 +1,40 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/set/set_cal.h" + +namespace Service { +namespace Set { + +SET_CAL::SET_CAL() : ServiceFramework("set:cal") { + static const FunctionInfo functions[] = { + {0, nullptr, "GetBluetoothBdAddress"}, + {1, nullptr, "GetConfigurationId1"}, + {2, nullptr, "GetAccelerometerOffset"}, + {3, nullptr, "GetAccelerometerScale"}, + {4, nullptr, "GetGyroscopeOffset"}, + {5, nullptr, "GetGyroscopeScale"}, + {6, nullptr, "GetWirelessLanMacAddress"}, + {7, nullptr, "GetWirelessLanCountryCodeCount"}, + {8, nullptr, "GetWirelessLanCountryCodes"}, + {9, nullptr, "GetSerialNumber"}, + {10, nullptr, "SetInitialSystemAppletProgramId"}, + {11, nullptr, "SetOverlayDispProgramId"}, + {12, nullptr, "GetBatteryLot"}, + {14, nullptr, "GetEciDeviceCertificate"}, + {15, nullptr, "GetEticketDeviceCertificate"}, + {16, nullptr, "GetSslKey"}, + {17, nullptr, "GetSslCertificate"}, + {18, nullptr, "GetGameCardKey"}, + {19, nullptr, "GetGameCardCertificate"}, + {20, nullptr, "GetEciDeviceKey"}, + {21, nullptr, "GetEticketDeviceKey"}, + {22, nullptr, "GetSpeakerParameter"}, + {23, nullptr, "GetLcdVendorId"}, + }; + RegisterHandlers(functions); +} + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/set_cal.h b/src/core/hle/service/set/set_cal.h new file mode 100644 index 000000000..9c0b851d0 --- /dev/null +++ b/src/core/hle/service/set/set_cal.h @@ -0,0 +1,19 @@ +// 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/service.h" + +namespace Service { +namespace Set { + +class SET_CAL final : public ServiceFramework<SET_CAL> { +public: + explicit SET_CAL(); + ~SET_CAL() = default; +}; + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/set_fd.cpp b/src/core/hle/service/set/set_fd.cpp new file mode 100644 index 000000000..8320d4250 --- /dev/null +++ b/src/core/hle/service/set/set_fd.cpp @@ -0,0 +1,25 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/set/set_fd.h" + +namespace Service { +namespace Set { + +SET_FD::SET_FD() : ServiceFramework("set:fd") { + static const FunctionInfo functions[] = { + {2, nullptr, "SetSettingsItemValue"}, + {3, nullptr, "ResetSettingsItemValue"}, + {4, nullptr, "CreateSettingsItemKeyIterator"}, + {10, nullptr, "ReadSettings"}, + {11, nullptr, "ResetSettings"}, + {20, nullptr, "SetWebInspectorFlag"}, + {21, nullptr, "SetAllowedSslHosts"}, + {22, nullptr, "SetHostFsMountPoint"}, + }; + RegisterHandlers(functions); +} + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/set_fd.h b/src/core/hle/service/set/set_fd.h new file mode 100644 index 000000000..65b36bcb3 --- /dev/null +++ b/src/core/hle/service/set/set_fd.h @@ -0,0 +1,19 @@ +// 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/service.h" + +namespace Service { +namespace Set { + +class SET_FD final : public ServiceFramework<SET_FD> { +public: + explicit SET_FD(); + ~SET_FD() = default; +}; + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp new file mode 100644 index 000000000..363abd10a --- /dev/null +++ b/src/core/hle/service/set/set_sys.cpp @@ -0,0 +1,167 @@ +// Copyright 2018 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/kernel/client_port.h" +#include "core/hle/service/set/set_sys.h" + +namespace Service { +namespace Set { + +void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) { + + IPC::ResponseBuilder rb{ctx, 3}; + + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); + + LOG_WARNING(Service_SET, "(STUBBED) called"); +} + +SET_SYS::SET_SYS() : ServiceFramework("set:sys") { + static const FunctionInfo functions[] = { + {0, nullptr, "SetLanguageCode"}, + {1, nullptr, "SetNetworkSettings"}, + {2, nullptr, "GetNetworkSettings"}, + {3, nullptr, "GetFirmwareVersion"}, + {4, nullptr, "GetFirmwareVersion2"}, + {7, nullptr, "GetLockScreenFlag"}, + {8, nullptr, "SetLockScreenFlag"}, + {9, nullptr, "GetBacklightSettings"}, + {10, nullptr, "SetBacklightSettings"}, + {11, nullptr, "SetBluetoothDevicesSettings"}, + {12, nullptr, "GetBluetoothDevicesSettings"}, + {13, nullptr, "GetExternalSteadyClockSourceId"}, + {14, nullptr, "SetExternalSteadyClockSourceId"}, + {15, nullptr, "GetUserSystemClockContext"}, + {16, nullptr, "SetUserSystemClockContext"}, + {17, nullptr, "GetAccountSettings"}, + {18, nullptr, "SetAccountSettings"}, + {19, nullptr, "GetAudioVolume"}, + {20, nullptr, "SetAudioVolume"}, + {21, nullptr, "GetEulaVersions"}, + {22, nullptr, "SetEulaVersions"}, + {23, &SET_SYS::GetColorSetId, "GetColorSetId"}, + {24, nullptr, "SetColorSetId"}, + {25, nullptr, "GetConsoleInformationUploadFlag"}, + {26, nullptr, "SetConsoleInformationUploadFlag"}, + {27, nullptr, "GetAutomaticApplicationDownloadFlag"}, + {28, nullptr, "SetAutomaticApplicationDownloadFlag"}, + {29, nullptr, "GetNotificationSettings"}, + {30, nullptr, "SetNotificationSettings"}, + {31, nullptr, "GetAccountNotificationSettings"}, + {32, nullptr, "SetAccountNotificationSettings"}, + {35, nullptr, "GetVibrationMasterVolume"}, + {36, nullptr, "SetVibrationMasterVolume"}, + {37, nullptr, "GetSettingsItemValueSize"}, + {38, nullptr, "GetSettingsItemValue"}, + {39, nullptr, "GetTvSettings"}, + {40, nullptr, "SetTvSettings"}, + {41, nullptr, "GetEdid"}, + {42, nullptr, "SetEdid"}, + {43, nullptr, "GetAudioOutputMode"}, + {44, nullptr, "SetAudioOutputMode"}, + {45, nullptr, "IsForceMuteOnHeadphoneRemoved"}, + {46, nullptr, "SetForceMuteOnHeadphoneRemoved"}, + {47, nullptr, "GetQuestFlag"}, + {48, nullptr, "SetQuestFlag"}, + {49, nullptr, "GetDataDeletionSettings"}, + {50, nullptr, "SetDataDeletionSettings"}, + {51, nullptr, "GetInitialSystemAppletProgramId"}, + {52, nullptr, "GetOverlayDispProgramId"}, + {53, nullptr, "GetDeviceTimeZoneLocationName"}, + {54, nullptr, "SetDeviceTimeZoneLocationName"}, + {55, nullptr, "GetWirelessCertificationFileSize"}, + {56, nullptr, "GetWirelessCertificationFile"}, + {57, nullptr, "SetRegionCode"}, + {58, nullptr, "GetNetworkSystemClockContext"}, + {59, nullptr, "SetNetworkSystemClockContext"}, + {60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"}, + {61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"}, + {62, nullptr, "GetDebugModeFlag"}, + {63, nullptr, "GetPrimaryAlbumStorage"}, + {64, nullptr, "SetPrimaryAlbumStorage"}, + {65, nullptr, "GetUsb30EnableFlag"}, + {66, nullptr, "SetUsb30EnableFlag"}, + {67, nullptr, "GetBatteryLot"}, + {68, nullptr, "GetSerialNumber"}, + {69, nullptr, "GetNfcEnableFlag"}, + {70, nullptr, "SetNfcEnableFlag"}, + {71, nullptr, "GetSleepSettings"}, + {72, nullptr, "SetSleepSettings"}, + {73, nullptr, "GetWirelessLanEnableFlag"}, + {74, nullptr, "SetWirelessLanEnableFlag"}, + {75, nullptr, "GetInitialLaunchSettings"}, + {76, nullptr, "SetInitialLaunchSettings"}, + {77, nullptr, "GetDeviceNickName"}, + {78, nullptr, "SetDeviceNickName"}, + {79, nullptr, "GetProductModel"}, + {80, nullptr, "GetLdnChannel"}, + {81, nullptr, "SetLdnChannel"}, + {82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"}, + {83, nullptr, "GetTelemetryDirtyFlags"}, + {84, nullptr, "GetPtmBatteryLot"}, + {85, nullptr, "SetPtmBatteryLot"}, + {86, nullptr, "GetPtmFuelGaugeParameter"}, + {87, nullptr, "SetPtmFuelGaugeParameter"}, + {88, nullptr, "GetBluetoothEnableFlag"}, + {89, nullptr, "SetBluetoothEnableFlag"}, + {90, nullptr, "GetMiiAuthorId"}, + {91, nullptr, "SetShutdownRtcValue"}, + {92, nullptr, "GetShutdownRtcValue"}, + {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, + {94, nullptr, "GetFatalDirtyFlags"}, + {95, nullptr, "GetAutoUpdateEnableFlag"}, + {96, nullptr, "SetAutoUpdateEnableFlag"}, + {97, nullptr, "GetNxControllerSettings"}, + {98, nullptr, "SetNxControllerSettings"}, + {99, nullptr, "GetBatteryPercentageFlag"}, + {100, nullptr, "SetBatteryPercentageFlag"}, + {101, nullptr, "GetExternalRtcResetFlag"}, + {102, nullptr, "SetExternalRtcResetFlag"}, + {103, nullptr, "GetUsbFullKeyEnableFlag"}, + {104, nullptr, "SetUsbFullKeyEnableFlag"}, + {105, nullptr, "SetExternalSteadyClockInternalOffset"}, + {106, nullptr, "GetExternalSteadyClockInternalOffset"}, + {107, nullptr, "GetBacklightSettingsEx"}, + {108, nullptr, "SetBacklightSettingsEx"}, + {109, nullptr, "GetHeadphoneVolumeWarningCount"}, + {110, nullptr, "SetHeadphoneVolumeWarningCount"}, + {111, nullptr, "GetBluetoothAfhEnableFlag"}, + {112, nullptr, "SetBluetoothAfhEnableFlag"}, + {113, nullptr, "GetBluetoothBoostEnableFlag"}, + {114, nullptr, "SetBluetoothBoostEnableFlag"}, + {115, nullptr, "GetInRepairProcessEnableFlag"}, + {116, nullptr, "SetInRepairProcessEnableFlag"}, + {117, nullptr, "GetHeadphoneVolumeUpdateFlag"}, + {118, nullptr, "SetHeadphoneVolumeUpdateFlag"}, + {119, nullptr, "NeedsToUpdateHeadphoneVolume"}, + {120, nullptr, "GetPushNotificationActivityModeOnSleep"}, + {121, nullptr, "SetPushNotificationActivityModeOnSleep"}, + {122, nullptr, "GetServiceDiscoveryControlSettings"}, + {123, nullptr, "SetServiceDiscoveryControlSettings"}, + {124, nullptr, "GetErrorReportSharePermission"}, + {125, nullptr, "SetErrorReportSharePermission"}, + {126, nullptr, "GetAppletLaunchFlags"}, + {127, nullptr, "SetAppletLaunchFlags"}, + {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, + {129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"}, + {130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"}, + {131, nullptr, "SetConsoleSixAxisSensorAngularVelocityBias"}, + {132, nullptr, "GetConsoleSixAxisSensorAccelerationGain"}, + {133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"}, + {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, + {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, + {136, nullptr, "GetKeyboardLayout"}, + {137, nullptr, "SetKeyboardLayout"}, + {138, nullptr, "GetWebInspectorFlag"}, + {139, nullptr, "GetAllowedSslHosts"}, + {140, nullptr, "GetHostFsMountPoint"}, + }; + RegisterHandlers(functions); +} + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h new file mode 100644 index 000000000..105f1a3c7 --- /dev/null +++ b/src/core/hle/service/set/set_sys.h @@ -0,0 +1,22 @@ +// 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/service.h" + +namespace Service { +namespace Set { + +class SET_SYS final : public ServiceFramework<SET_SYS> { +public: + explicit SET_SYS(); + ~SET_SYS() = default; + +private: + void GetColorSetId(Kernel::HLERequestContext& ctx); +}; + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/settings.cpp b/src/core/hle/service/set/settings.cpp new file mode 100644 index 000000000..c6bc9e240 --- /dev/null +++ b/src/core/hle/service/set/settings.cpp @@ -0,0 +1,22 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/set/set.h" +#include "core/hle/service/set/set_cal.h" +#include "core/hle/service/set/set_fd.h" +#include "core/hle/service/set/set_sys.h" +#include "core/hle/service/set/settings.h" + +namespace Service { +namespace Set { + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared<SET>()->InstallAsService(service_manager); + std::make_shared<SET_CAL>()->InstallAsService(service_manager); + std::make_shared<SET_FD>()->InstallAsService(service_manager); + std::make_shared<SET_SYS>()->InstallAsService(service_manager); +} + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/set/settings.h b/src/core/hle/service/set/settings.h new file mode 100644 index 000000000..6c8d5a58c --- /dev/null +++ b/src/core/hle/service/set/settings.h @@ -0,0 +1,16 @@ +// 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/service.h" + +namespace Service { +namespace Set { + +/// Registers all Settings services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Set +} // namespace Service diff --git a/src/core/hle/service/sockets/bsd_u.cpp b/src/core/hle/service/sockets/bsd_u.cpp index 629ffb040..2ca1000ca 100644 --- a/src/core/hle/service/sockets/bsd_u.cpp +++ b/src/core/hle/service/sockets/bsd_u.cpp @@ -17,6 +17,15 @@ void BSD_U::RegisterClient(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } +void BSD_U::StartMonitoring(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); // bsd errno +} + void BSD_U::Socket(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -67,6 +76,7 @@ void BSD_U::Close(Kernel::HLERequestContext& ctx) { BSD_U::BSD_U() : ServiceFramework("bsd:u") { static const FunctionInfo functions[] = {{0, &BSD_U::RegisterClient, "RegisterClient"}, + {1, &BSD_U::StartMonitoring, "StartMonitoring"}, {2, &BSD_U::Socket, "Socket"}, {11, &BSD_U::SendTo, "SendTo"}, {14, &BSD_U::Connect, "Connect"}, diff --git a/src/core/hle/service/sockets/bsd_u.h b/src/core/hle/service/sockets/bsd_u.h index fde08a22b..4e1252e9d 100644 --- a/src/core/hle/service/sockets/bsd_u.h +++ b/src/core/hle/service/sockets/bsd_u.h @@ -17,6 +17,7 @@ public: private: void RegisterClient(Kernel::HLERequestContext& ctx); + void StartMonitoring(Kernel::HLERequestContext& ctx); void Socket(Kernel::HLERequestContext& ctx); void Connect(Kernel::HLERequestContext& ctx); void SendTo(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 364ddcea2..ad49f4265 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -146,6 +146,13 @@ void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); } +void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<ISystemClock>(); + LOG_DEBUG(Service_Time, "called"); +} + Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) : ServiceFramework(name), time(std::move(time)) {} diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 1cbbadb21..197029e7a 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -56,6 +56,7 @@ public: void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx); void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); void GetTimeZoneService(Kernel::HLERequestContext& ctx); + void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); protected: std::shared_ptr<Module> time; diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp index 1634d3300..b172b2bd6 100644 --- a/src/core/hle/service/time/time_s.cpp +++ b/src/core/hle/service/time/time_s.cpp @@ -10,6 +10,10 @@ namespace Time { TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") { static const FunctionInfo functions[] = { {0, &TIME_S::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, + {1, &TIME_S::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, + {2, &TIME_S::GetStandardSteadyClock, "GetStandardSteadyClock"}, + {3, &TIME_S::GetTimeZoneService, "GetTimeZoneService"}, + {4, &TIME_S::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/time/time_u.cpp b/src/core/hle/service/time/time_u.cpp index ae4f78adf..fc1ace325 100644 --- a/src/core/hle/service/time/time_u.cpp +++ b/src/core/hle/service/time/time_u.cpp @@ -13,6 +13,7 @@ TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time) {1, &TIME_U::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, {2, &TIME_U::GetStandardSteadyClock, "GetStandardSteadyClock"}, {3, &TIME_U::GetTimeZoneService, "GetTimeZoneService"}, + {4, &TIME_U::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 8b4ed30d2..0aa621dfe 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -8,6 +8,7 @@ #include "common/scope_exit.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_m.h" @@ -38,6 +39,7 @@ public: template <typename T> T Read() { + ASSERT(read_index + sizeof(T) <= buffer.size()); T val; std::memcpy(&val, buffer.data() + read_index, sizeof(T)); read_index += sizeof(T); @@ -47,6 +49,7 @@ public: template <typename T> T ReadUnaligned() { + ASSERT(read_index + sizeof(T) <= buffer.size()); T val; std::memcpy(&val, buffer.data() + read_index, sizeof(T)); read_index += sizeof(T); @@ -54,6 +57,7 @@ public: } std::vector<u8> ReadBlock(size_t length) { + ASSERT(read_index + length <= buffer.size()); const u8* const begin = buffer.data() + read_index; const u8* const end = begin + length; std::vector<u8> data(begin, end); @@ -86,7 +90,18 @@ public: write_index = Common::AlignUp(write_index, 4); } + template <typename T> + void WriteObject(const T& val) { + u32_le size = static_cast<u32>(sizeof(val)); + Write(size); + // TODO(Subv): Support file descriptors. + Write<u32_le>(0); // Fd count. + Write(val); + } + void Deserialize() { + ASSERT(buffer.size() > sizeof(Header)); + Header header{}; std::memcpy(&header, buffer.data(), sizeof(Header)); @@ -262,10 +277,11 @@ public: Data data; }; -// TODO(bunnei): Remove this. When set to 1, games will think a fence is valid and boot further. -// This will break libnx and potentially other apps that more stringently check this. This is here -// purely as a convenience, and should go away once we implement fences. -static constexpr u32 FENCE_HACK = 0; +struct BufferProducerFence { + u32 is_valid; + std::array<Nvidia::IoctlFence, 4> fences; +}; +static_assert(sizeof(BufferProducerFence) == 36, "BufferProducerFence has wrong size"); class IGBPDequeueBufferResponseParcel : public Parcel { public: @@ -274,20 +290,16 @@ public: protected: void SerializeData() override { - // TODO(bunnei): Find out what this all means. Writing anything non-zero here breaks libnx. - Write<u32>(0); - Write<u32>(FENCE_HACK); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); - Write<u32>(0); + // TODO(Subv): Find out how this Fence is used. + BufferProducerFence fence = {}; + fence.is_valid = 1; + for (auto& fence_ : fence.fences) + fence_.id = -1; + + Write(slot); + Write<u32_le>(1); + WriteObject(fence); + Write<u32_le>(0); } u32_le slot; @@ -316,11 +328,10 @@ public: protected: void SerializeData() override { - // TODO(bunnei): Find out what this all means. Writing anything non-zero here breaks libnx. - Write<u32_le>(0); - Write<u32_le>(FENCE_HACK); - Write<u32_le>(0); - Write(buffer); + // TODO(Subv): Figure out what this value means, writing non-zero here will make libnx try + // to read an IGBPBuffer object from the parcel. + Write<u32_le>(1); + WriteObject(buffer); Write<u32_le>(0); } @@ -429,7 +440,7 @@ public: {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, - {3, &IHOSBinderDriver::TransactParcelAuto, "TransactParcelAuto"}, + {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, }; RegisterHandlers(functions); } @@ -453,95 +464,61 @@ private: SetPreallocatedBuffer = 14 }; - void TransactParcel(u32 id, TransactionId transaction, const std::vector<u8>& input_data, - VAddr output_addr, u64 output_size) { + void TransactParcel(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u32 id = rp.Pop<u32>(); + auto transaction = static_cast<TransactionId>(rp.Pop<u32>()); + u32 flags = rp.Pop<u32>(); auto buffer_queue = nv_flinger->GetBufferQueue(id); + LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); + if (transaction == TransactionId::Connect) { - IGBPConnectRequestParcel request{input_data}; + IGBPConnectRequestParcel request{ctx.ReadBuffer()}; IGBPConnectResponseParcel response{1280, 720}; - std::vector<u8> response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); + ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::SetPreallocatedBuffer) { - IGBPSetPreallocatedBufferRequestParcel request{input_data}; + IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()}; buffer_queue->SetPreallocatedBuffer(request.data.slot, request.buffer); IGBPSetPreallocatedBufferResponseParcel response{}; - std::vector<u8> response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); + ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::DequeueBuffer) { - IGBPDequeueBufferRequestParcel request{input_data}; + IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; u32 slot = buffer_queue->DequeueBuffer(request.data.pixel_format, request.data.width, request.data.height); IGBPDequeueBufferResponseParcel response{slot}; - std::vector<u8> response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); + ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::RequestBuffer) { - IGBPRequestBufferRequestParcel request{input_data}; + IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()}; auto& buffer = buffer_queue->RequestBuffer(request.slot); IGBPRequestBufferResponseParcel response{buffer}; - std::vector<u8> response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); + ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::QueueBuffer) { - IGBPQueueBufferRequestParcel request{input_data}; + IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; buffer_queue->QueueBuffer(request.data.slot, request.data.transform); IGBPQueueBufferResponseParcel response{1280, 720}; - std::vector<u8> response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); + ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::Query) { - IGBPQueryRequestParcel request{input_data}; + IGBPQueryRequestParcel request{ctx.ReadBuffer()}; u32 value = buffer_queue->Query(static_cast<NVFlinger::BufferQueue::QueryType>(request.type)); IGBPQueryResponseParcel response{value}; - std::vector<u8> response_buffer = response.Serialize(); - Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size()); + ctx.WriteBuffer(response.Serialize()); } else if (transaction == TransactionId::CancelBuffer) { LOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); } else { ASSERT_MSG(false, "Unimplemented"); } - } - - void TransactParcel(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - u32 id = rp.Pop<u32>(); - auto transaction = static_cast<TransactionId>(rp.Pop<u32>()); - u32 flags = rp.Pop<u32>(); - LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); - - auto& input_buffer = ctx.BufferDescriptorA()[0]; - auto& output_buffer = ctx.BufferDescriptorB()[0]; - std::vector<u8> input_data(input_buffer.Size()); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size()); - - TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - } - - void TransactParcelAuto(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - u32 id = rp.Pop<u32>(); - auto transaction = static_cast<TransactionId>(rp.Pop<u32>()); - u32 flags = rp.Pop<u32>(); - LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); - - auto& input_buffer = ctx.BufferDescriptorX()[0]; - auto& output_buffer = ctx.BufferDescriptorC()[0]; - std::vector<u8> input_data(input_buffer.size); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.size); - - TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -719,18 +696,13 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { u64 layer_id = rp.Pop<u64>(); u64 aruid = rp.Pop<u64>(); - auto& buffer = ctx.BufferDescriptorB()[0]; - u64 display_id = nv_flinger->OpenDisplay(display_name); u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); NativeWindow native_window{buffer_queue_id}; - auto data = native_window.Serialize(); - Memory::WriteBlock(buffer.Address(), data.data(), data.size()); - IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); rb.Push(RESULT_SUCCESS); - rb.Push<u64>(data.size()); + rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize())); } void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) { @@ -741,21 +713,16 @@ void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx rp.Pop<u32>(); // padding u64 display_id = rp.Pop<u64>(); - auto& buffer = ctx.BufferDescriptorB()[0]; - // TODO(Subv): What's the difference between a Stray and a Managed layer? u64 layer_id = nv_flinger->CreateLayer(display_id); u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); NativeWindow native_window{buffer_queue_id}; - auto data = native_window.Serialize(); - Memory::WriteBlock(buffer.Address(), data.data(), data.size()); - IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0); rb.Push(RESULT_SUCCESS); rb.Push(layer_id); - rb.Push<u64>(data.size()); + rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize())); } void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) { @@ -781,8 +748,7 @@ void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& void IApplicationDisplayService::ListDisplays(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; DisplayInfo display_info; - auto& buffer = ctx.BufferDescriptorB()[0]; - Memory::WriteBlock(buffer.Address(), &display_info, sizeof(DisplayInfo)); + ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); rb.Push(RESULT_SUCCESS); rb.Push<u64>(1); |