diff options
Diffstat (limited to 'src/core')
52 files changed, 1072 insertions, 360 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6c0911070..6f8104516 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -22,6 +22,8 @@ add_library(core STATIC file_sys/romfs_filesystem.h file_sys/savedata_factory.cpp file_sys/savedata_factory.h + file_sys/sdmc_factory.cpp + file_sys/sdmc_factory.h file_sys/storage.h frontend/emu_window.cpp frontend/emu_window.h @@ -140,6 +142,10 @@ add_library(core STATIC hle/service/nifm/nifm_s.h hle/service/nifm/nifm_u.cpp hle/service/nifm/nifm_u.h + hle/service/nfp/nfp.cpp + hle/service/nfp/nfp.h + hle/service/nfp/nfp_user.cpp + hle/service/nfp/nfp_user.h hle/service/ns/ns.cpp hle/service/ns/ns.h hle/service/ns/pl_u.cpp @@ -187,8 +193,10 @@ add_library(core STATIC hle/service/sm/controller.h hle/service/sm/sm.cpp hle/service/sm/sm.h - hle/service/sockets/bsd_u.cpp - hle/service/sockets/bsd_u.h + hle/service/sockets/bsd.cpp + hle/service/sockets/bsd.h + hle/service/sockets/nsd.cpp + hle/service/sockets/nsd.h hle/service/sockets/sfdnsres.cpp hle/service/sockets/sfdnsres.h hle/service/sockets/sockets.cpp @@ -199,6 +207,8 @@ add_library(core STATIC hle/service/spl/module.h hle/service/spl/spl.cpp hle/service/spl/spl.h + hle/service/ssl/ssl.cpp + hle/service/ssl/ssl.h hle/service/time/time.cpp hle/service/time/time.h hle/service/time/time_s.cpp diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 7d83f9717..6afad0e0c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -86,21 +86,17 @@ public: } void AddTicks(u64 ticks) override { - if (ticks > ticks_remaining) { - ticks_remaining = 0; - return; - } - ticks -= ticks_remaining; + CoreTiming::AddTicks(ticks - num_interpreted_instructions); + num_interpreted_instructions = 0; } u64 GetTicksRemaining() override { - return ticks_remaining; + return std::max(CoreTiming::GetDowncount(), 0); } u64 GetCNTPCT() override { return CoreTiming::GetTicks(); } ARM_Dynarmic& parent; - size_t ticks_remaining = 0; size_t num_interpreted_instructions = 0; u64 tpidrro_el0 = 0; u64 tpidr_el0 = 0; diff --git a/src/core/core.cpp b/src/core/core.cpp index d55621de8..11654d4da 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -148,19 +148,15 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { current_process = Kernel::Process::Create("main"); - switch (Settings::values.cpu_core) { - case Settings::CpuCore::Unicorn: - cpu_core = std::make_shared<ARM_Unicorn>(); - break; - case Settings::CpuCore::Dynarmic: - default: + if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 cpu_core = std::make_shared<ARM_Dynarmic>(); #else cpu_core = std::make_shared<ARM_Unicorn>(); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif - break; + } else { + cpu_core = std::make_shared<ARM_Unicorn>(); } gpu_core = std::make_unique<Tegra::GPU>(); diff --git a/src/core/core.h b/src/core/core.h index 552c8f5ee..ade456cfc 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -13,6 +13,7 @@ #include "core/memory.h" #include "core/perf_stats.h" #include "core/telemetry_session.h" +#include "video_core/debug_utils/debug_utils.h" #include "video_core/gpu.h" class EmuWindow; @@ -135,6 +136,14 @@ public: return *app_loader; } + void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) { + debug_context = std::move(context); + } + + std::shared_ptr<Tegra::DebugContext> GetGPUDebugContext() const { + return debug_context; + } + private: /** * Initialize the emulated system. @@ -154,6 +163,8 @@ private: std::unique_ptr<Kernel::Scheduler> scheduler; std::unique_ptr<Tegra::GPU> gpu_core; + std::shared_ptr<Tegra::DebugContext> debug_context; + Kernel::SharedPtr<Kernel::Process> current_process; /// When true, signals that a reschedule should happen diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h index 5a40bf472..c7639795e 100644 --- a/src/core/file_sys/directory.h +++ b/src/core/file_sys/directory.h @@ -6,34 +6,28 @@ #include <array> #include <cstddef> +#include "common/common_funcs.h" #include "common/common_types.h" +#include "core/file_sys/filesystem.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace namespace FileSys { -// Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format -const size_t FILENAME_LENGTH = 0x20C / 2; +// Structure of a directory entry, from +// http://switchbrew.org/index.php?title=Filesystem_services#DirectoryEntry +const size_t FILENAME_LENGTH = 0x300; struct Entry { - char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) - std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) - char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) - std::array<char, 4> - extension; // 8.3 file extension (set to spaces for directories, null-terminated) - char unknown2; // unknown (always 0x01) - char unknown3; // unknown (0x00 or 0x08) - char is_directory; // directory flag - char is_hidden; // hidden flag - char is_archive; // archive flag - char is_read_only; // read-only flag - u64 file_size; // file size (for files only) + char filename[FILENAME_LENGTH]; + INSERT_PADDING_BYTES(4); + EntryType type; + INSERT_PADDING_BYTES(3); + u64 file_size; }; -static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); -static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); -static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry."); -static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); -static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); +static_assert(sizeof(Entry) == 0x310, "Directory Entry struct isn't exactly 0x310 bytes long!"); +static_assert(offsetof(Entry, type) == 0x304, "Wrong offset for type in Entry."); +static_assert(offsetof(Entry, file_size) == 0x308, "Wrong offset for file_size in Entry."); class DirectoryBackend : NonCopyable { public: @@ -46,7 +40,10 @@ public: * @param entries Buffer to read data into * @return Number of entries listed */ - virtual u32 Read(const u32 count, Entry* entries) = 0; + virtual u64 Read(const u64 count, Entry* entries) = 0; + + /// Returns the number of entries still left to read. + virtual u64 GetEntryCount() const = 0; /** * Close the directory diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp index 22b17ba04..4235f3935 100644 --- a/src/core/file_sys/disk_filesystem.cpp +++ b/src/core/file_sys/disk_filesystem.cpp @@ -11,16 +11,43 @@ namespace FileSys { +static std::string ModeFlagsToString(Mode mode) { + std::string mode_str; + u32 mode_flags = static_cast<u32>(mode); + + // Calculate the correct open mode for the file. + if ((mode_flags & static_cast<u32>(Mode::Read)) && + (mode_flags & static_cast<u32>(Mode::Write))) { + if (mode_flags & static_cast<u32>(Mode::Append)) + mode_str = "a+"; + else + mode_str = "r+"; + } else { + if (mode_flags & static_cast<u32>(Mode::Read)) + mode_str = "r"; + else if (mode_flags & static_cast<u32>(Mode::Append)) + mode_str = "a"; + else if (mode_flags & static_cast<u32>(Mode::Write)) + mode_str = "w"; + } + + mode_str += "b"; + + return mode_str; +} + std::string Disk_FileSystem::GetName() const { return "Disk"; } ResultVal<std::unique_ptr<StorageBackend>> Disk_FileSystem::OpenFile(const std::string& path, Mode mode) const { - ASSERT_MSG(mode == Mode::Read || mode == Mode::Write, "Other file modes are not supported"); + + // Calculate the correct open mode for the file. + std::string mode_str = ModeFlagsToString(mode); std::string full_path = base_directory + path; - auto file = std::make_shared<FileUtil::IOFile>(full_path, mode == Mode::Read ? "rb" : "wb"); + auto file = std::make_shared<FileUtil::IOFile>(full_path, mode_str.c_str()); if (!file->IsOpen()) { return ERROR_PATH_NOT_FOUND; @@ -75,8 +102,15 @@ ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const return ResultCode(-1); } -ResultCode Disk_FileSystem::CreateDirectory(const Path& path) const { - LOG_WARNING(Service_FS, "(STUBBED) called"); +ResultCode Disk_FileSystem::CreateDirectory(const std::string& path) const { + // TODO(Subv): Perform path validation to prevent escaping the emulator sandbox. + std::string full_path = base_directory + path; + + if (FileUtil::CreateDir(full_path)) { + return RESULT_SUCCESS; + } + + LOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating %s", full_path.c_str()); // TODO(wwylele): Use correct error code return ResultCode(-1); } @@ -88,8 +122,17 @@ ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& de } ResultVal<std::unique_ptr<DirectoryBackend>> Disk_FileSystem::OpenDirectory( - const Path& path) const { - return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<Disk_Directory>()); + const std::string& path) const { + + std::string full_path = base_directory + path; + + if (!FileUtil::IsDirectory(full_path)) { + // TODO(Subv): Find the correct error code for this. + return ResultCode(-1); + } + + auto directory = std::make_unique<Disk_Directory>(full_path); + return MakeResult<std::unique_ptr<DirectoryBackend>>(std::move(directory)); } u64 Disk_FileSystem::GetFreeSpaceSize() const { @@ -103,8 +146,10 @@ ResultVal<FileSys::EntryType> Disk_FileSystem::GetEntryType(const std::string& p return ERROR_PATH_NOT_FOUND; } - // TODO(Subv): Find out the EntryType values - UNIMPLEMENTED_MSG("Unimplemented GetEntryType"); + if (FileUtil::IsDirectory(full_path)) + return MakeResult(EntryType::Directory); + + return MakeResult(EntryType::File); } ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { @@ -129,18 +174,55 @@ u64 Disk_Storage::GetSize() const { } bool Disk_Storage::SetSize(const u64 size) const { - LOG_WARNING(Service_FS, "(STUBBED) called"); - return false; + file->Resize(size); + file->Flush(); + return true; } -u32 Disk_Directory::Read(const u32 count, Entry* entries) { - LOG_WARNING(Service_FS, "(STUBBED) called"); - return 0; +Disk_Directory::Disk_Directory(const std::string& path) : directory() { + unsigned size = FileUtil::ScanDirectoryTree(path, directory); + directory.size = size; + directory.isDirectory = true; + children_iterator = directory.children.begin(); } -bool Disk_Directory::Close() const { - LOG_WARNING(Service_FS, "(STUBBED) called"); - return true; +u64 Disk_Directory::Read(const u64 count, Entry* entries) { + u64 entries_read = 0; + + while (entries_read < count && children_iterator != directory.children.cend()) { + const FileUtil::FSTEntry& file = *children_iterator; + const std::string& filename = file.virtualName; + Entry& entry = entries[entries_read]; + + LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, + file.isDirectory); + + // TODO(Link Mauve): use a proper conversion to UTF-16. + for (size_t j = 0; j < FILENAME_LENGTH; ++j) { + entry.filename[j] = filename[j]; + if (!filename[j]) + break; + } + + if (file.isDirectory) { + entry.file_size = 0; + entry.type = EntryType::Directory; + } else { + entry.file_size = file.size; + entry.type = EntryType::File; + } + + ++entries_read; + ++children_iterator; + } + return entries_read; +} + +u64 Disk_Directory::GetEntryCount() const { + // We convert the children iterator into a const_iterator to allow template argument deduction + // in std::distance. + std::vector<FileUtil::FSTEntry>::const_iterator current = children_iterator; + return std::distance(current, directory.children.end()); } } // namespace FileSys diff --git a/src/core/file_sys/disk_filesystem.h b/src/core/file_sys/disk_filesystem.h index 53767b949..742d7db1a 100644 --- a/src/core/file_sys/disk_filesystem.h +++ b/src/core/file_sys/disk_filesystem.h @@ -30,9 +30,10 @@ public: ResultCode DeleteDirectory(const Path& path) const override; ResultCode DeleteDirectoryRecursively(const Path& path) const override; ResultCode CreateFile(const std::string& path, u64 size) const override; - ResultCode CreateDirectory(const Path& path) const override; + ResultCode CreateDirectory(const std::string& path) const override; ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; - ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; + ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory( + const std::string& path) const override; u64 GetFreeSpaceSize() const override; ResultVal<EntryType> GetEntryType(const std::string& path) const override; @@ -59,8 +60,26 @@ private: class Disk_Directory : public DirectoryBackend { public: - u32 Read(const u32 count, Entry* entries) override; - bool Close() const override; + Disk_Directory(const std::string& path); + + ~Disk_Directory() override { + Close(); + } + + u64 Read(const u64 count, Entry* entries) override; + u64 GetEntryCount() const override; + + bool Close() const override { + return true; + } + +protected: + u32 total_entries_in_directory; + FileUtil::FSTEntry directory; + + // We need to remember the last entry we returned, so a subsequent call to Read will continue + // from the next one. This iterator will always point to the next unread entry. + std::vector<FileUtil::FSTEntry>::iterator children_iterator; }; } // namespace FileSys diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h index 94ad2abf2..399427ca2 100644 --- a/src/core/file_sys/filesystem.h +++ b/src/core/file_sys/filesystem.h @@ -27,7 +27,7 @@ enum LowPathType : u32 { Wchar = 4, }; -enum EntryType : u32 { +enum EntryType : u8 { Directory = 0, File = 1, }; @@ -35,6 +35,7 @@ enum EntryType : u32 { enum class Mode : u32 { Read = 1, Write = 2, + Append = 4, }; class Path { @@ -103,7 +104,7 @@ public: * @param path Path relative to the archive * @return Result of the operation */ - virtual ResultCode CreateDirectory(const Path& path) const = 0; + virtual ResultCode CreateDirectory(const std::string& path) const = 0; /** * Delete a directory specified by its path @@ -149,7 +150,8 @@ public: * @param path Path relative to the archive * @return Opened directory, or error code */ - virtual ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const = 0; + virtual ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory( + const std::string& path) const = 0; /** * Get the free space diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp index f1f9b4d04..0c6cc3157 100644 --- a/src/core/file_sys/romfs_filesystem.cpp +++ b/src/core/file_sys/romfs_filesystem.cpp @@ -55,7 +55,7 @@ ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const return ResultCode(-1); } -ResultCode RomFS_FileSystem::CreateDirectory(const Path& path) const { +ResultCode RomFS_FileSystem::CreateDirectory(const std::string& path) const { LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).", GetName().c_str()); // TODO(wwylele): Use correct error code @@ -70,7 +70,8 @@ ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& d } ResultVal<std::unique_ptr<DirectoryBackend>> RomFS_FileSystem::OpenDirectory( - const Path& path) const { + const std::string& path) const { + LOG_WARNING(Service_FS, "Opening Directory in a ROMFS archive"); return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<ROMFSDirectory>()); } diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h index cedd70645..3f94c04d0 100644 --- a/src/core/file_sys/romfs_filesystem.h +++ b/src/core/file_sys/romfs_filesystem.h @@ -36,9 +36,10 @@ public: ResultCode DeleteDirectory(const Path& path) const override; ResultCode DeleteDirectoryRecursively(const Path& path) const override; ResultCode CreateFile(const std::string& path, u64 size) const override; - ResultCode CreateDirectory(const Path& path) const override; + ResultCode CreateDirectory(const std::string& path) const override; ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; - ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; + ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory( + const std::string& path) const override; u64 GetFreeSpaceSize() const override; ResultVal<EntryType> GetEntryType(const std::string& path) const override; @@ -70,7 +71,10 @@ private: class ROMFSDirectory : public DirectoryBackend { public: - u32 Read(const u32 count, Entry* entries) override { + u64 Read(const u64 count, Entry* entries) override { + return 0; + } + u64 GetEntryCount() const override { return 0; } bool Close() const override { diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp new file mode 100644 index 000000000..00e80d2a7 --- /dev/null +++ b/src/core/file_sys/sdmc_factory.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 <cinttypes> +#include <memory> +#include "common/common_types.h" +#include "common/logging/log.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/file_sys/disk_filesystem.h" +#include "core/file_sys/sdmc_factory.h" + +namespace FileSys { + +SDMC_Factory::SDMC_Factory(std::string sd_directory) : sd_directory(std::move(sd_directory)) {} + +ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& path) { + // Create the SD Card directory if it doesn't already exist. + if (!FileUtil::IsDirectory(sd_directory)) { + FileUtil::CreateFullPath(sd_directory); + } + + auto archive = std::make_unique<Disk_FileSystem>(sd_directory); + return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); +} + +ResultCode SDMC_Factory::Format(const Path& path) { + LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); + // TODO(Subv): Find the right error code for this + return ResultCode(-1); +} + +ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const { + LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); + // TODO(bunnei): Find the right error code for this + return ResultCode(-1); +} + +} // namespace FileSys diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h new file mode 100644 index 000000000..93becda25 --- /dev/null +++ b/src/core/file_sys/sdmc_factory.h @@ -0,0 +1,31 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include "common/common_types.h" +#include "core/file_sys/filesystem.h" +#include "core/hle/result.h" + +namespace FileSys { + +/// File system interface to the SDCard archive +class SDMC_Factory final : public FileSystemFactory { +public: + explicit SDMC_Factory(std::string sd_directory); + + std::string GetName() const override { + return "SDMC_Factory"; + } + ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override; + ResultCode Format(const Path& path) override; + ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; + +private: + std::string sd_directory; +}; + +} // namespace FileSys diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ffcbfe64f..bef4f15f5 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -268,8 +268,11 @@ std::vector<u8> HLERequestContext::ReadBuffer() const { size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size) const { const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; - - ASSERT_MSG(size <= GetWriteBufferSize(), "Size %lx is too big", size); + const size_t buffer_size{GetWriteBufferSize()}; + if (size > buffer_size) { + LOG_CRITICAL(Core, "size (%016zx) is greater than buffer_size (%016zx)", size, buffer_size); + size = buffer_size; // TODO(bunnei): This needs to be HW tested + } if (is_buffer_b) { Memory::WriteBlock(BufferDescriptorB()[0].Address(), buffer, size); diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 3694afc60..2cffec198 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -121,8 +121,9 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part // of the user address space. vm_manager - .MapMemoryBlock(Memory::STACK_VADDR, std::make_shared<std::vector<u8>>(stack_size, 0), 0, - stack_size, MemoryState::Mapped) + .MapMemoryBlock(Memory::STACK_AREA_VADDR_END - stack_size, + std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, + MemoryState::Mapped) .Unwrap(); misc_memory_used += stack_size; memory_region->used += stack_size; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 311ab4187..171bbd956 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -756,8 +756,16 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 return RESULT_SUCCESS; } -static ResultCode SetThreadCoreMask(u64, u64, u64) { - LOG_WARNING(Kernel_SVC, "(STUBBED) called"); +static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) { + LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle); + *mask = 0x0; + *unknown = 0xf; + return RESULT_SUCCESS; +} + +static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) { + LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, mask=0x%08X, unknown=0x%lx", handle, + mask, unknown); return RESULT_SUCCESS; } @@ -809,7 +817,7 @@ static const FunctionDef SVC_Table[] = { {0x0B, SvcWrap<SleepThread>, "SleepThread"}, {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, - {0x0E, nullptr, "GetThreadCoreMask"}, + {0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"}, {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, {0x11, nullptr, "SignalEvent"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index b224f5e67..5da4f5269 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -70,6 +70,21 @@ void SvcWrap() { FuncReturn(retval); } +template <ResultCode func(u32, u32, u64)> +void SvcWrap() { + FuncReturn(func((u32)(PARAM(0) & 0xFFFFFFFF), (u32)(PARAM(1) & 0xFFFFFFFF), PARAM(2)).raw); +} + +template <ResultCode func(u32, u32*, u64*)> +void SvcWrap() { + u32 param_1 = 0; + u64 param_2 = 0; + ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), ¶m_1, ¶m_2); + Core::CPU().SetReg(1, param_1); + Core::CPU().SetReg(2, param_2); + FuncReturn(retval.raw); +} + template <ResultCode func(u64, u64, u32, u32)> void SvcWrap() { FuncReturn( diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 145f50887..f3a8aa4aa 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -342,7 +342,7 @@ SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority, // Initialize new "main" thread auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, - Memory::STACK_VADDR_END, owner_process); + Memory::STACK_AREA_VADDR_END, owner_process); SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 97fef7a48..052f49979 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -200,6 +200,9 @@ public: } ResultVal& operator=(const ResultVal& o) { + if (this == &o) { + return *this; + } if (!empty()) { if (!o.empty()) { object = o.object; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d9f003ed4..bab338205 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -12,6 +12,7 @@ #include "core/hle/service/apm/apm.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/nvflinger/nvflinger.h" +#include "core/settings.h" namespace Service { namespace AM { @@ -241,17 +242,20 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { } void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { + const bool use_docked_mode{Settings::values.use_docked_mode}; IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(static_cast<u8>(OperationMode::Handheld)); + rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); LOG_WARNING(Service_AM, "(STUBBED) called"); } void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { + const bool use_docked_mode{Settings::values.use_docked_mode}; IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld)); + rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked + : APM::PerformanceMode::Handheld)); LOG_WARNING(Service_AM, "(STUBBED) called"); } diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 1cbca6c4b..6d0461bbc 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -59,12 +59,12 @@ private: AudioRendererResponseData response_data{}; response_data.section_0_size = - response_data.state_entries.size() * sizeof(AudioRendererStateEntry); - response_data.section_1_size = response_data.section_1.size(); - response_data.section_2_size = response_data.section_2.size(); - response_data.section_3_size = response_data.section_3.size(); - response_data.section_4_size = response_data.section_4.size(); - response_data.section_5_size = response_data.section_5.size(); + static_cast<u32>(response_data.state_entries.size() * sizeof(AudioRendererStateEntry)); + response_data.section_1_size = static_cast<u32>(response_data.section_1.size()); + response_data.section_2_size = static_cast<u32>(response_data.section_2.size()); + response_data.section_3_size = static_cast<u32>(response_data.section_3.size()); + response_data.section_4_size = static_cast<u32>(response_data.section_4.size()); + response_data.section_5_size = static_cast<u32>(response_data.section_5.size()); response_data.total_size = sizeof(AudioRendererResponseData); for (unsigned i = 0; i < response_data.state_entries.size(); i++) { @@ -151,12 +151,80 @@ private: Kernel::SharedPtr<Kernel::Event> system_event; }; +class IAudioDevice final : public ServiceFramework<IAudioDevice> { +public: + IAudioDevice() : ServiceFramework("IAudioDevice") { + static const FunctionInfo functions[] = { + {0x0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, + {0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, + {0x2, nullptr, "GetAudioDeviceOutputVolume"}, + {0x3, nullptr, "GetActiveAudioDeviceName"}, + {0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"}, + {0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"}, + {0x6, nullptr, "ListAudioDeviceNameAuto"}, + {0x7, nullptr, "SetAudioDeviceOutputVolumeAuto"}, + {0x8, nullptr, "GetAudioDeviceOutputVolumeAuto"}, + {0x10, nullptr, "GetActiveAudioDeviceNameAuto"}, + {0x11, nullptr, "QueryAudioDeviceInputEvent"}, + {0x12, nullptr, "QueryAudioDeviceOutputEvent"}}; + RegisterHandlers(functions); + + buffer_event = + Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioOutBufferReleasedEvent"); + } + +private: + void ListAudioDeviceName(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + const std::string audio_interface = "AudioInterface"; + ctx.WriteBuffer(audio_interface.c_str(), audio_interface.size()); + + IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(1); + } + + void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + f32 volume = static_cast<f32>(rp.Pop<u32>()); + + auto file_buffer = ctx.ReadBuffer(); + auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); + + IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + rb.Push(RESULT_SUCCESS); + } + + void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + + buffer_event->Signal(); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(buffer_event); + } + + void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(1); + } + + Kernel::SharedPtr<Kernel::Event> buffer_event; + +}; // namespace Audio + AudRenU::AudRenU() : ServiceFramework("audren:u") { static const FunctionInfo functions[] = { {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, - {2, &AudRenU::GetAudioRenderersProcessMasterVolume, "GetAudioRenderersProcessMasterVolume"}, - {3, nullptr, "SetAudioRenderersProcessMasterVolume"}, + {2, &AudRenU::GetAudioDevice, "GetAudioDevice"}, }; RegisterHandlers(functions); } @@ -179,12 +247,13 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); } -void AudRenU::GetAudioRenderersProcessMasterVolume(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; +void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(100); - LOG_WARNING(Service_Audio, "(STUBBED) called"); + rb.PushIpcInterface<Audio::IAudioDevice>(); + + LOG_DEBUG(Service_Audio, "called"); } } // namespace Audio diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 939d353a9..f59d1627d 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h @@ -21,7 +21,7 @@ public: private: void OpenAudioRenderer(Kernel::HLERequestContext& ctx); void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); - void GetAudioRenderersProcessMasterVolume(Kernel::HLERequestContext& ctx); + void GetAudioDevice(Kernel::HLERequestContext& ctx); }; } // namespace Audio diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index ef05955b9..945832e98 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -6,6 +6,7 @@ #include "common/file_util.h" #include "core/file_sys/filesystem.h" #include "core/file_sys/savedata_factory.h" +#include "core/file_sys/sdmc_factory.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" @@ -60,9 +61,13 @@ void RegisterFileSystems() { filesystem_map.clear(); std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); + std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX); auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory)); RegisterFileSystem(std::move(savedata), Type::SaveData); + + auto sdcard = std::make_unique<FileSys::SDMC_Factory>(std::move(sd_directory)); + RegisterFileSystem(std::move(sdcard), Type::SDMC); } void InstallInterfaces(SM::ServiceManager& service_manager) { diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 8d30e94a1..56d26146e 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -26,6 +26,7 @@ namespace FileSystem { enum class Type { RomFS = 1, SaveData = 2, + SDMC = 3, }; /** diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index e5ce41671..89fa70ae6 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -5,6 +5,7 @@ #include <cinttypes> #include "common/logging/log.h" #include "core/core.h" +#include "core/file_sys/directory.h" #include "core/file_sys/filesystem.h" #include "core/file_sys/storage.h" #include "core/hle/ipc_helpers.h" @@ -71,8 +72,8 @@ 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"}, + {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, nullptr, "Flush"}, + {3, &IFile::SetSize, "SetSize"}, {4, &IFile::GetSize, "GetSize"}, }; RegisterHandlers(functions); } @@ -149,6 +150,75 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + + void SetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 size = rp.Pop<u64>(); + backend->SetSize(size); + LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void GetSize(Kernel::HLERequestContext& ctx) { + const u64 size = backend->GetSize(); + LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push<u64>(size); + } +}; + +class IDirectory final : public ServiceFramework<IDirectory> { +public: + explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend) + : ServiceFramework("IDirectory"), backend(std::move(backend)) { + static const FunctionInfo functions[] = { + {0, &IDirectory::Read, "Read"}, + {1, &IDirectory::GetEntryCount, "GetEntryCount"}, + }; + RegisterHandlers(functions); + } + +private: + std::unique_ptr<FileSys::DirectoryBackend> backend; + + void Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 unk = rp.Pop<u64>(); + + LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk); + + // Calculate how many entries we can fit in the output buffer + u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); + + // Read the data from the Directory backend + std::vector<FileSys::Entry> entries(count_entries); + u64 read_entries = backend->Read(count_entries, entries.data()); + + // Convert the data into a byte array + std::vector<u8> output(entries.size() * sizeof(FileSys::Entry)); + std::memcpy(output.data(), entries.data(), output.size()); + + // Write the data to memory + ctx.WriteBuffer(output); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(read_entries); + } + + void GetEntryCount(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "called"); + + u64 count = backend->GetEntryCount(); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(count); + } }; class IFileSystem final : public ServiceFramework<IFileSystem> { @@ -157,8 +227,10 @@ public: : ServiceFramework("IFileSystem"), backend(std::move(backend)) { static const FunctionInfo functions[] = { {0, &IFileSystem::CreateFile, "CreateFile"}, + {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, {7, &IFileSystem::GetEntryType, "GetEntryType"}, {8, &IFileSystem::OpenFile, "OpenFile"}, + {9, &IFileSystem::OpenDirectory, "OpenDirectory"}, {10, &IFileSystem::Commit, "Commit"}, }; RegisterHandlers(functions); @@ -182,6 +254,20 @@ public: rb.Push(backend->CreateFile(name, size)); } + void CreateDirectory(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 directory %s", name.c_str()); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(backend->CreateDirectory(name)); + } + void OpenFile(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -208,6 +294,33 @@ public: rb.PushIpcInterface<IFile>(std::move(file)); } + void OpenDirectory(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); + + // TODO(Subv): Implement this filter. + u32 filter_flags = rp.Pop<u32>(); + + LOG_DEBUG(Service_FS, "called directory %s filter %u", name.c_str(), filter_flags); + + auto result = backend->OpenDirectory(name); + if (result.Failed()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result.Code()); + return; + } + + auto directory = std::move(result.Unwrap()); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IDirectory>(std::move(directory)); + } + void GetEntryType(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -274,10 +387,14 @@ void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) { } void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_FS, "(STUBBED) called"); + LOG_DEBUG(Service_FS, "called"); - IPC::ResponseBuilder rb{ctx, 2}; + FileSys::Path unused; + auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IFileSystem>(std::move(filesystem)); } void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 7e04ad8d4..019a09444 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -65,13 +65,14 @@ private: } void UpdatePadCallback(u64 userdata, int cycles_late) { - SharedMemory* mem = reinterpret_cast<SharedMemory*>(shared_mem->GetPointer()); + SharedMemory mem{}; + std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory)); if (is_device_reload_pending.exchange(false)) LoadInputDevices(); // Set up controllers as neon red+blue Joy-Con attached to console - ControllerHeader& controller_header = mem->controllers[Controller_Handheld].header; + ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header; controller_header.type = ControllerType_Handheld | ControllerType_JoyconPair; controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent; controller_header.right_color_body = JOYCON_BODY_NEON_RED; @@ -79,8 +80,8 @@ private: controller_header.left_color_body = JOYCON_BODY_NEON_BLUE; controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE; - for (int layoutIdx = 0; layoutIdx < HID_NUM_LAYOUTS; layoutIdx++) { - ControllerLayout& layout = mem->controllers[Controller_Handheld].layouts[layoutIdx]; + for (int index = 0; index < HID_NUM_LAYOUTS; index++) { + ControllerLayout& layout = mem.controllers[Controller_Handheld].layouts[index]; layout.header.num_entries = HID_NUM_ENTRIES; layout.header.max_entry_index = HID_NUM_ENTRIES - 1; @@ -136,10 +137,25 @@ private: // layouts) } - // TODO(shinyquagsire23): Update touch info + // TODO(bunnei): Properly implement the touch screen, the below will just write empty data + + TouchScreen& touchscreen = mem.touchscreen; + const u64 last_entry = touchscreen.header.latest_entry; + const u64 curr_entry = (last_entry + 1) % touchscreen.entries.size(); + const u64 timestamp = CoreTiming::GetTicks(); + const u64 sample_counter = touchscreen.entries[last_entry].header.timestamp + 1; + touchscreen.header.timestamp_ticks = timestamp; + touchscreen.header.num_entries = touchscreen.entries.size(); + touchscreen.header.latest_entry = curr_entry; + touchscreen.header.max_entry_index = touchscreen.entries.size(); + touchscreen.header.timestamp = timestamp; + touchscreen.entries[curr_entry].header.timestamp = sample_counter; + touchscreen.entries[curr_entry].header.num_touches = 0; // TODO(shinyquagsire23): Signal events + std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory)); + // Reschedule recurrent event CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); } @@ -185,6 +201,7 @@ public: {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"}, {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"}, {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, + {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"}, {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"}, {103, &Hid::ActivateNpad, "ActivateNpad"}, {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, @@ -193,7 +210,7 @@ public: {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"}, - {124, nullptr, "SetNpadJoyAssignmentModeDual"}, + {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, {201, &Hid::SendVibrationValue, "SendVibrationValue"}, @@ -265,6 +282,13 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -315,6 +339,12 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void SetNpadJoyAssignmentModeDual(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); diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp new file mode 100644 index 000000000..49870841c --- /dev/null +++ b/src/core/hle/service/nfp/nfp.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/nfp/nfp.h" +#include "core/hle/service/nfp/nfp_user.h" + +namespace Service { +namespace NFP { + +Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) + : ServiceFramework(name), module(std::move(module)) {} + +void Module::Interface::Unknown(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NFP, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + auto module = std::make_shared<Module>(); + std::make_shared<NFP_User>(module)->InstallAsService(service_manager); +} + +} // namespace NFP +} // namespace Service diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h new file mode 100644 index 000000000..1163e9954 --- /dev/null +++ b/src/core/hle/service/nfp/nfp.h @@ -0,0 +1,28 @@ +// 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 NFP { + +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; + }; +}; + +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace NFP +} // namespace Service diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp new file mode 100644 index 000000000..14e5647c4 --- /dev/null +++ b/src/core/hle/service/nfp/nfp_user.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/nfp/nfp_user.h" + +namespace Service { +namespace NFP { + +NFP_User::NFP_User(std::shared_ptr<Module> module) + : Module::Interface(std::move(module), "nfp:user") { + static const FunctionInfo functions[] = { + {0, &NFP_User::Unknown, "Unknown"}, + }; + RegisterHandlers(functions); +} + +} // namespace NFP +} // namespace Service diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h new file mode 100644 index 000000000..1606444ca --- /dev/null +++ b/src/core/hle/service/nfp/nfp_user.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/nfp/nfp.h" + +namespace Service { +namespace NFP { + +class NFP_User final : public Module::Interface { +public: + explicit NFP_User(std::shared_ptr<Module> module); +}; + +} // namespace NFP +} // namespace Service diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index 695e295ca..ef3c7799a 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp @@ -33,6 +33,7 @@ enum class LoadState : u32 { PL_U::PL_U() : ServiceFramework("pl:u") { static const FunctionInfo functions[] = { + {0, &PL_U::RequestLoad, "RequestLoad"}, {1, &PL_U::GetLoadState, "GetLoadState"}, {2, &PL_U::GetSize, "GetSize"}, {3, &PL_U::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, @@ -54,6 +55,15 @@ PL_U::PL_U() : ServiceFramework("pl:u") { } } +void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 shared_font_type{rp.Pop<u32>()}; + + LOG_DEBUG(Service_NS, "called, shared_font_type=%d", shared_font_type); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 font_id{rp.Pop<u32>()}; diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h index 7a4766338..360482d13 100644 --- a/src/core/hle/service/ns/pl_u.h +++ b/src/core/hle/service/ns/pl_u.h @@ -17,6 +17,7 @@ public: ~PL_U() = default; private: + void RequestLoad(Kernel::HLERequestContext& ctx); void GetLoadState(Kernel::HLERequestContext& ctx); void GetSize(Kernel::HLERequestContext& ctx); void GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 94530724e..87b3a2d74 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -26,14 +26,13 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 "Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr, offset, width, height, stride, format); - using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; - using Flags = NVFlinger::BufferQueue::BufferTransformFlags; - const bool flip_vertical = static_cast<u32>(transform) & static_cast<u32>(Flags::FlipV); - const RendererBase::FramebufferInfo framebuffer_info{ - addr, offset, width, height, stride, static_cast<PixelFormat>(format), flip_vertical}; + using PixelFormat = Tegra::FramebufferConfig::PixelFormat; + const Tegra::FramebufferConfig framebuffer{ + addr, offset, width, height, stride, static_cast<PixelFormat>(format), transform}; Core::System::GetInstance().perf_stats.EndGameFrame(); - VideoCore::g_renderer->SwapBuffers(framebuffer_info); + + VideoCore::g_renderer->SwapBuffers(framebuffer); } } // namespace Devices diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 686eadca7..1de5767cb 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -47,6 +47,8 @@ public: ~BufferQueue() = default; enum class BufferTransformFlags : u32 { + /// No transform flags are set + Unset = 0x00, /// Flip source image horizontally (around the vertical axis) FlipH = 0x01, /// Flip source image vertically (around the horizontal axis) diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 005cc1e0b..c5490c1ae 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -25,6 +25,7 @@ #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/nfp/nfp.h" #include "core/hle/service/nifm/nifm.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/nvdrv/nvdrv.h" @@ -35,6 +36,7 @@ #include "core/hle/service/sm/sm.h" #include "core/hle/service/sockets/sockets.h" #include "core/hle/service/spl/module.h" +#include "core/hle/service/ssl/ssl.h" #include "core/hle/service/time/time.h" #include "core/hle/service/vi/vi.h" @@ -110,15 +112,15 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext auto cmd_buf = ctx.CommandBuffer(); std::string function_name = info == nullptr ? fmt::format("{}", ctx.GetCommand()) : info->name; - fmt::MemoryWriter w; - w.write("function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name, - cmd_buf[0]); + fmt::memory_buffer buf; + fmt::format_to(buf, "function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name, + cmd_buf[0]); for (int i = 1; i <= 8; ++i) { - w.write(", [{}]={:#x}", i, cmd_buf[i]); + fmt::format_to(buf, ", [{}]={:#x}", i, cmd_buf[i]); } - w << '}'; + buf.push_back('}'); - LOG_ERROR(Service, "unknown / unimplemented %s", w.c_str()); + LOG_ERROR(Service, "unknown / unimplemented %s", fmt::to_string(buf).c_str()); UNIMPLEMENTED(); } @@ -186,12 +188,14 @@ void Init() { Friend::InstallInterfaces(*SM::g_service_manager); HID::InstallInterfaces(*SM::g_service_manager); LM::InstallInterfaces(*SM::g_service_manager); + NFP::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); SPL::InstallInterfaces(*SM::g_service_manager); + SSL::InstallInterfaces(*SM::g_service_manager); Time::InstallInterfaces(*SM::g_service_manager); VI::InstallInterfaces(*SM::g_service_manager, nv_flinger); Set::InstallInterfaces(*SM::g_service_manager); diff --git a/src/core/hle/service/sockets/bsd_u.cpp b/src/core/hle/service/sockets/bsd.cpp index 2ca1000ca..790ff82b3 100644 --- a/src/core/hle/service/sockets/bsd_u.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -3,12 +3,12 @@ // Refer to the license.txt file included. #include "core/hle/ipc_helpers.h" -#include "core/hle/service/sockets/bsd_u.h" +#include "core/hle/service/sockets/bsd.h" namespace Service { namespace Sockets { -void BSD_U::RegisterClient(Kernel::HLERequestContext& ctx) { +void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -17,7 +17,7 @@ void BSD_U::RegisterClient(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD_U::StartMonitoring(Kernel::HLERequestContext& ctx) { +void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -26,7 +26,7 @@ void BSD_U::StartMonitoring(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD_U::Socket(Kernel::HLERequestContext& ctx) { +void BSD::Socket(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; u32 domain = rp.Pop<u32>(); @@ -44,7 +44,7 @@ void BSD_U::Socket(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD_U::Connect(Kernel::HLERequestContext& ctx) { +void BSD::Connect(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -54,7 +54,7 @@ void BSD_U::Connect(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD_U::SendTo(Kernel::HLERequestContext& ctx) { +void BSD::SendTo(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -64,7 +64,7 @@ void BSD_U::SendTo(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -void BSD_U::Close(Kernel::HLERequestContext& ctx) { +void BSD::Close(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; @@ -74,13 +74,15 @@ void BSD_U::Close(Kernel::HLERequestContext& ctx) { rb.Push<u32>(0); // bsd errno } -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"}, - {26, &BSD_U::Close, "Close"}}; +BSD::BSD(const char* name) : ServiceFramework(name) { + static const FunctionInfo functions[] = { + {0, &BSD::RegisterClient, "RegisterClient"}, + {1, &BSD::StartMonitoring, "StartMonitoring"}, + {2, &BSD::Socket, "Socket"}, + {11, &BSD::SendTo, "SendTo"}, + {14, &BSD::Connect, "Connect"}, + {26, &BSD::Close, "Close"}, + }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/sockets/bsd_u.h b/src/core/hle/service/sockets/bsd.h index 4e1252e9d..32d949e95 100644 --- a/src/core/hle/service/sockets/bsd_u.h +++ b/src/core/hle/service/sockets/bsd.h @@ -10,10 +10,10 @@ namespace Service { namespace Sockets { -class BSD_U final : public ServiceFramework<BSD_U> { +class BSD final : public ServiceFramework<BSD> { public: - BSD_U(); - ~BSD_U() = default; + explicit BSD(const char* name); + ~BSD() = default; private: void RegisterClient(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp new file mode 100644 index 000000000..e3542d325 --- /dev/null +++ b/src/core/hle/service/sockets/nsd.cpp @@ -0,0 +1,34 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/sockets/nsd.h" + +namespace Service { +namespace Sockets { + +NSD::NSD(const char* name) : ServiceFramework(name) { + static const FunctionInfo functions[] = { + {10, nullptr, "GetSettingName"}, + {11, nullptr, "GetEnvironmentIdentifier"}, + {12, nullptr, "GetDeviceId"}, + {13, nullptr, "DeleteSettings"}, + {14, nullptr, "ImportSettings"}, + {20, nullptr, "Resolve"}, + {21, nullptr, "ResolveEx"}, + {30, nullptr, "GetNasServiceSetting"}, + {31, nullptr, "GetNasServiceSettingEx"}, + {40, nullptr, "GetNasRequestFqdn"}, + {41, nullptr, "GetNasRequestFqdnEx"}, + {42, nullptr, "GetNasApiFqdn"}, + {43, nullptr, "GetNasApiFqdnEx"}, + {50, nullptr, "GetCurrentSetting"}, + {60, nullptr, "ReadSaveDataFromFsForTest"}, + {61, nullptr, "WriteSaveDataToFsForTest"}, + {62, nullptr, "DeleteSaveDataOfFsForTest"}, + }; + RegisterHandlers(functions); +} + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h new file mode 100644 index 000000000..a7c15a860 --- /dev/null +++ b/src/core/hle/service/sockets/nsd.h @@ -0,0 +1,20 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace Sockets { + +class NSD final : public ServiceFramework<NSD> { +public: + explicit NSD(const char* name); + ~NSD() = default; +}; + +} // namespace Sockets +} // namespace Service diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 4d7bc7c3e..eb4b5fa57 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -19,16 +19,18 @@ void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) { } SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") { - static const FunctionInfo functions[] = {{0, nullptr, "SetDnsAddressesPrivate"}, - {1, nullptr, "GetDnsAddressPrivate"}, - {2, nullptr, "GetHostByName"}, - {3, nullptr, "GetHostByAddr"}, - {4, nullptr, "GetHostStringError"}, - {5, nullptr, "GetGaiStringError"}, - {6, &SFDNSRES::GetAddrInfo, "GetAddrInfo"}, - {7, nullptr, "GetNameInfo"}, - {8, nullptr, "RequestCancelHandle"}, - {9, nullptr, "CancelSocketCall"}}; + static const FunctionInfo functions[] = { + {0, nullptr, "SetDnsAddressesPrivate"}, + {1, nullptr, "GetDnsAddressPrivate"}, + {2, nullptr, "GetHostByName"}, + {3, nullptr, "GetHostByAddr"}, + {4, nullptr, "GetHostStringError"}, + {5, nullptr, "GetGaiStringError"}, + {6, &SFDNSRES::GetAddrInfo, "GetAddrInfo"}, + {7, nullptr, "GetNameInfo"}, + {8, nullptr, "RequestCancelHandle"}, + {9, nullptr, "CancelSocketCall"}, + }; RegisterHandlers(functions); } diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h index b726a30fd..c07cc1594 100644 --- a/src/core/hle/service/sockets/sfdnsres.h +++ b/src/core/hle/service/sockets/sfdnsres.h @@ -12,7 +12,7 @@ namespace Sockets { class SFDNSRES final : public ServiceFramework<SFDNSRES> { public: - SFDNSRES(); + explicit SFDNSRES(); ~SFDNSRES() = default; private: diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp index f1396eaa1..cedc276d9 100644 --- a/src/core/hle/service/sockets/sockets.cpp +++ b/src/core/hle/service/sockets/sockets.cpp @@ -2,7 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/sockets/bsd_u.h" +#include "core/hle/service/sockets/bsd.h" +#include "core/hle/service/sockets/nsd.h" #include "core/hle/service/sockets/sfdnsres.h" #include "core/hle/service/sockets/sockets.h" @@ -10,7 +11,10 @@ namespace Service { namespace Sockets { void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<BSD_U>()->InstallAsService(service_manager); + std::make_shared<BSD>("bsd:s")->InstallAsService(service_manager); + std::make_shared<BSD>("bsd:u")->InstallAsService(service_manager); + std::make_shared<NSD>("nsd:a")->InstallAsService(service_manager); + std::make_shared<NSD>("nsd:u")->InstallAsService(service_manager); std::make_shared<SFDNSRES>()->InstallAsService(service_manager); } diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp new file mode 100644 index 000000000..afa8d5d79 --- /dev/null +++ b/src/core/hle/service/ssl/ssl.cpp @@ -0,0 +1,17 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/ssl/ssl.h" + +namespace Service { +namespace SSL { + +SSL::SSL() : ServiceFramework("ssl") {} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared<SSL>()->InstallAsService(service_manager); +} + +} // namespace SSL +} // namespace Service diff --git a/src/core/hle/service/ssl/ssl.h b/src/core/hle/service/ssl/ssl.h new file mode 100644 index 000000000..645dad003 --- /dev/null +++ b/src/core/hle/service/ssl/ssl.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 SSL { + +class SSL final : public ServiceFramework<SSL> { +public: + explicit SSL(); + ~SSL() = default; +}; + +/// Registers all SSL services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace SSL +} // namespace Service diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index aa09ed323..8b4ee970f 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -76,7 +76,7 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& fil } else if (Common::ToLower(virtual_name) == "sdk") { is_sdk_found = true; } else { - // Contrinue searching + // Continue searching return true; } diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 0ba8c6fd2..e9f462196 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -414,7 +414,7 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) { process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); - process->Run(codeset->entrypoint, 48, Memory::STACK_SIZE); + process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 6dcd1ce48..b5133e4d6 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -137,7 +137,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) { process->address_mappings = default_address_mappings; process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); - process->Run(base_addr, 48, Memory::STACK_SIZE); + process->Run(base_addr, 48, Memory::DEFAULT_STACK_SIZE); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 100aa022e..3bc10ed0d 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -165,7 +165,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) { process->address_mappings = default_address_mappings; process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); - process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Memory::STACK_SIZE); + process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Memory::DEFAULT_STACK_SIZE); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index a9beccb95..291bf066f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -15,6 +15,7 @@ #include "core/core.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" +#include "core/hle/lock.h" #include "core/memory.h" #include "core/memory_setup.h" #include "video_core/renderer_base.h" @@ -41,6 +42,9 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa LOG_DEBUG(HW_Memory, "Mapping %p onto %016" PRIX64 "-%016" PRIX64, memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); + RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE, + FlushMode::FlushAndInvalidate); + VAddr end = base + size; while (base != end) { ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %016" PRIX64, base); @@ -112,91 +116,120 @@ static std::set<MemoryHookPointer> GetSpecialHandlers(VAddr vaddr, u64 size) { return GetSpecialHandlers(page_table, vaddr, size); } -template <typename T> -boost::optional<T> ReadSpecial(VAddr addr); +/** + * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) + * using a VMA from the current process + */ +static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { + u8* direct_pointer = nullptr; + + auto& vm_manager = process.vm_manager; + + auto it = vm_manager.FindVMA(vaddr); + ASSERT(it != vm_manager.vma_map.end()); + + auto& vma = it->second; + switch (vma.type) { + case Kernel::VMAType::AllocatedMemoryBlock: + direct_pointer = vma.backing_block->data() + vma.offset; + break; + case Kernel::VMAType::BackingMemory: + direct_pointer = vma.backing_memory; + break; + case Kernel::VMAType::Free: + return nullptr; + default: + UNREACHABLE(); + } + + return direct_pointer + (vaddr - vma.base); +} + +/** + * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) + * using a VMA from the current process. + */ +static u8* GetPointerFromVMA(VAddr vaddr) { + return GetPointerFromVMA(*Core::CurrentProcess(), vaddr); +} template <typename T> T Read(const VAddr vaddr) { - if ((vaddr >> PAGE_BITS) >= PAGE_TABLE_NUM_ENTRIES) { - LOG_ERROR(HW_Memory, "Read%lu after page table @ 0x%016" PRIX64, sizeof(T) * 8, vaddr); - return 0; + const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) { + // NOTE: Avoid adding any extra logic to this fast-path block + T value; + std::memcpy(&value, &page_pointer[vaddr & PAGE_MASK], sizeof(T)); + return value; } - const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state + std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); + + PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: - LOG_ERROR(HW_Memory, "unmapped Read%zu @ 0x%016" PRIX64, sizeof(T) * 8, vaddr); + LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr); return 0; - case PageType::Special: { - if (auto result = ReadSpecial<T>(vaddr)) - return *result; - [[fallthrough]]; - } - case PageType::Memory: { - const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; - ASSERT_MSG(page_pointer, "Mapped memory page without a pointer @ %016" PRIX64, vaddr); + case PageType::Memory: + ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); + break; + case PageType::RasterizerCachedMemory: { + RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); T value; - std::memcpy(&value, &page_pointer[vaddr & PAGE_MASK], sizeof(T)); + std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); return value; } + default: + UNREACHABLE(); } - UNREACHABLE(); - return 0; } template <typename T> -bool WriteSpecial(VAddr addr, const T data); - -template <typename T> void Write(const VAddr vaddr, const T data) { - if ((vaddr >> PAGE_BITS) >= PAGE_TABLE_NUM_ENTRIES) { - LOG_ERROR(HW_Memory, "Write%lu after page table 0x%08X @ 0x%016" PRIX64, sizeof(data) * 8, - (u32)data, vaddr); + u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) { + // NOTE: Avoid adding any extra logic to this fast-path block + std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); return; } - const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state + std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); + + PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: - LOG_ERROR(HW_Memory, "unmapped Write%zu 0x%08X @ 0x%016" PRIX64, sizeof(data) * 8, - static_cast<u32>(data), vaddr); - return; - case PageType::Special: { - if (WriteSpecial<T>(vaddr, data)) - return; - [[fallthrough]]; - } - case PageType::Memory: { - u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; - ASSERT_MSG(page_pointer, "Mapped memory page without a pointer @ %016" PRIX64, vaddr); - std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); + LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, + vaddr); return; + case PageType::Memory: + ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); + break; + case PageType::RasterizerCachedMemory: { + RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); + std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); + break; } + default: + UNREACHABLE(); } - UNREACHABLE(); } bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { auto& page_table = process.vm_manager.page_table; - if ((vaddr >> PAGE_BITS) >= PAGE_TABLE_NUM_ENTRIES) - return false; + const u8* page_pointer = page_table.pointers[vaddr >> PAGE_BITS]; + if (page_pointer) + return true; - const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; - switch (type) { - case PageType::Unmapped: - return false; - case PageType::Memory: + if (page_table.attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) return true; - case PageType::Special: { - for (auto handler : GetSpecialHandlers(page_table, vaddr, 1)) - if (auto result = handler->IsValidAddress(vaddr)) - return *result; - return current_page_table->pointers[vaddr >> PAGE_BITS] != nullptr; - } - } - UNREACHABLE(); + + if (page_table.attributes[vaddr >> PAGE_BITS] != PageType::Special) + return false; + return false; } @@ -214,7 +247,11 @@ u8* GetPointer(const VAddr vaddr) { return page_pointer + (vaddr & PAGE_MASK); } - LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%016" PRIx64, vaddr); + if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { + return GetPointerFromVMA(vaddr); + } + + LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr); return nullptr; } @@ -288,6 +325,95 @@ u8* GetPhysicalPointer(PAddr address) { return target_pointer; } +void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { + if (start == 0) { + return; + } + + u64 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; + VAddr vaddr = start; + + for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) { + PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; + + if (cached) { + // Switch page type to cached if now cached + switch (page_type) { + case PageType::Unmapped: + // It is not necessary for a process to have this region mapped into its address + // space, for example, a system module need not have a VRAM mapping. + break; + case PageType::Memory: + page_type = PageType::RasterizerCachedMemory; + current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; + break; + default: + UNREACHABLE(); + } + } else { + // Switch page type to uncached if now uncached + switch (page_type) { + case PageType::Unmapped: + // It is not necessary for a process to have this region mapped into its address + // space, for example, a system module need not have a VRAM mapping. + break; + case PageType::RasterizerCachedMemory: { + u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); + if (pointer == nullptr) { + // It's possible that this function has been called while updating the pagetable + // after unmapping a VMA. In that case the underlying VMA will no longer exist, + // and we should just leave the pagetable entry blank. + page_type = PageType::Unmapped; + } else { + page_type = PageType::Memory; + current_page_table->pointers[vaddr >> PAGE_BITS] = pointer; + } + break; + } + default: + UNREACHABLE(); + } + } + } +} + +void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { + // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be + // null here + if (VideoCore::g_renderer == nullptr) { + return; + } + + VAddr end = start + size; + + auto CheckRegion = [&](VAddr region_start, VAddr region_end) { + if (start >= region_end || end <= region_start) { + // No overlap with region + return; + } + + VAddr overlap_start = std::max(start, region_start); + VAddr overlap_end = std::min(end, region_end); + u64 overlap_size = overlap_end - overlap_start; + + auto* rasterizer = VideoCore::g_renderer->Rasterizer(); + switch (mode) { + case FlushMode::Flush: + rasterizer->FlushRegion(overlap_start, overlap_size); + break; + case FlushMode::Invalidate: + rasterizer->InvalidateRegion(overlap_start, overlap_size); + break; + case FlushMode::FlushAndInvalidate: + rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size); + break; + } + }; + + CheckRegion(PROCESS_IMAGE_VADDR, PROCESS_IMAGE_VADDR_END); + CheckRegion(HEAP_VADDR, HEAP_VADDR_END); +} + u8 Read8(const VAddr addr) { return Read<u8>(addr); } @@ -304,17 +430,6 @@ u64 Read64(const VAddr addr) { return Read<u64_le>(addr); } -static bool ReadSpecialBlock(const Kernel::Process& process, const VAddr src_addr, - void* dest_buffer, const size_t size) { - auto& page_table = process.vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, src_addr, size)) { - if (handler->ReadBlock(src_addr, dest_buffer, size)) { - return true; - } - } - return false; -} - void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, const size_t size) { auto& page_table = process.vm_manager.page_table; @@ -324,21 +439,16 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ size_t page_offset = src_addr & PAGE_MASK; while (remaining_size > 0) { - const size_t copy_amount = std::min<size_t>(PAGE_SIZE - page_offset, remaining_size); + const size_t copy_amount = + std::min(static_cast<size_t>(PAGE_SIZE) - page_offset, remaining_size); const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); switch (page_table.attributes[page_index]) { - case PageType::Unmapped: - LOG_ERROR(HW_Memory, - "unmapped ReadBlock @ 0x%016" PRIX64 " (start address = 0x%" PRIx64 - ", size = %zu)", + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); std::memset(dest_buffer, 0, copy_amount); break; - case PageType::Special: { - if (ReadSpecialBlock(process, current_vaddr, dest_buffer, copy_amount)) - break; - [[fallthrough]]; } case PageType::Memory: { DEBUG_ASSERT(page_table.pointers[page_index]); @@ -347,6 +457,12 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ std::memcpy(dest_buffer, src_ptr, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), + FlushMode::Flush); + std::memcpy(dest_buffer, GetPointerFromVMA(process, current_vaddr), copy_amount); + break; + } default: UNREACHABLE(); } @@ -378,17 +494,6 @@ void Write64(const VAddr addr, const u64 data) { Write<u64_le>(addr, data); } -static bool WriteSpecialBlock(const Kernel::Process& process, const VAddr dest_addr, - const void* src_buffer, const size_t size) { - auto& page_table = process.vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, dest_addr, size)) { - if (handler->WriteBlock(dest_addr, src_buffer, size)) { - return true; - } - } - return false; -} - void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, const size_t size) { auto& page_table = process.vm_manager.page_table; @@ -397,20 +502,17 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi size_t page_offset = dest_addr & PAGE_MASK; while (remaining_size > 0) { - const size_t copy_amount = std::min<size_t>(PAGE_SIZE - page_offset, remaining_size); + const size_t copy_amount = + std::min(static_cast<size_t>(PAGE_SIZE) - page_offset, remaining_size); const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); switch (page_table.attributes[page_index]) { - case PageType::Unmapped: + case PageType::Unmapped: { LOG_ERROR(HW_Memory, - "unmapped WriteBlock @ 0x%016" PRIX64 " (start address = 0x%016" PRIX64 - ", size = %zu)", + "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); break; - case PageType::Special: - if (WriteSpecialBlock(process, current_vaddr, src_buffer, copy_amount)) - break; - [[fallthrough]]; + } case PageType::Memory: { DEBUG_ASSERT(page_table.pointers[page_index]); @@ -418,6 +520,12 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi std::memcpy(dest_ptr, src_buffer, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), + FlushMode::Invalidate); + std::memcpy(GetPointerFromVMA(process, current_vaddr), src_buffer, copy_amount); + break; + } default: UNREACHABLE(); } @@ -433,9 +541,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size WriteBlock(*Core::CurrentProcess(), dest_addr, src_buffer, size); } -void ZeroBlock(const VAddr dest_addr, const size_t size) { - const auto& process = *Core::CurrentProcess(); - +void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const size_t size) { + auto& page_table = process.vm_manager.page_table; size_t remaining_size = size; size_t page_index = dest_addr >> PAGE_BITS; size_t page_offset = dest_addr & PAGE_MASK; @@ -443,27 +550,29 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { static const std::array<u8, PAGE_SIZE> zeros = {}; while (remaining_size > 0) { - const size_t copy_amount = std::min<size_t>(PAGE_SIZE - page_offset, remaining_size); + const size_t copy_amount = + std::min(static_cast<size_t>(PAGE_SIZE) - page_offset, remaining_size); const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); - switch (current_page_table->attributes[page_index]) { - case PageType::Unmapped: - LOG_ERROR(HW_Memory, - "unmapped ZeroBlock @ 0x%016" PRIX64 " (start address = 0x%016" PRIX64 - ", size = %zu)", + switch (page_table.attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); break; - case PageType::Special: - if (WriteSpecialBlock(process, current_vaddr, zeros.data(), copy_amount)) - break; - [[fallthrough]]; + } case PageType::Memory: { - DEBUG_ASSERT(current_page_table->pointers[page_index]); + DEBUG_ASSERT(page_table.pointers[page_index]); - u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; + u8* dest_ptr = page_table.pointers[page_index] + page_offset; std::memset(dest_ptr, 0, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), + FlushMode::Invalidate); + std::memset(GetPointerFromVMA(process, current_vaddr), 0, copy_amount); + break; + } default: UNREACHABLE(); } @@ -474,37 +583,34 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { } } -void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { - const auto& process = *Core::CurrentProcess(); - +void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, const size_t size) { + auto& page_table = process.vm_manager.page_table; size_t remaining_size = size; size_t page_index = src_addr >> PAGE_BITS; size_t page_offset = src_addr & PAGE_MASK; while (remaining_size > 0) { - const size_t copy_amount = std::min<size_t>(PAGE_SIZE - page_offset, remaining_size); + const size_t copy_amount = + std::min(static_cast<size_t>(PAGE_SIZE) - page_offset, remaining_size); const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); - switch (current_page_table->attributes[page_index]) { - case PageType::Unmapped: - LOG_ERROR(HW_Memory, - "unmapped CopyBlock @ 0x%016" PRIX64 " (start address = 0x%016" PRIX64 - ", size = %zu)", + switch (page_table.attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); - ZeroBlock(dest_addr, copy_amount); + ZeroBlock(process, dest_addr, copy_amount); break; - case PageType::Special: { - std::vector<u8> buffer(copy_amount); - if (ReadSpecialBlock(process, current_vaddr, buffer.data(), buffer.size())) { - WriteBlock(dest_addr, buffer.data(), buffer.size()); - break; - } - [[fallthrough]]; } case PageType::Memory: { - DEBUG_ASSERT(current_page_table->pointers[page_index]); - const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; - WriteBlock(dest_addr, src_ptr, copy_amount); + DEBUG_ASSERT(page_table.pointers[page_index]); + const u8* src_ptr = page_table.pointers[page_index] + page_offset; + WriteBlock(process, dest_addr, src_ptr, copy_amount); + break; + } + case PageType::RasterizerCachedMemory: { + RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), + FlushMode::Flush); + WriteBlock(process, dest_addr, GetPointerFromVMA(process, current_vaddr), copy_amount); break; } default: @@ -519,78 +625,6 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { } } -template <> -boost::optional<u8> ReadSpecial<u8>(VAddr addr) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u8))) - if (auto result = handler->Read8(addr)) - return *result; - return {}; -} - -template <> -boost::optional<u16> ReadSpecial<u16>(VAddr addr) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u16))) - if (auto result = handler->Read16(addr)) - return *result; - return {}; -} - -template <> -boost::optional<u32> ReadSpecial<u32>(VAddr addr) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u32))) - if (auto result = handler->Read32(addr)) - return *result; - return {}; -} - -template <> -boost::optional<u64> ReadSpecial<u64>(VAddr addr) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u64))) - if (auto result = handler->Read64(addr)) - return *result; - return {}; -} - -template <> -bool WriteSpecial<u8>(VAddr addr, const u8 data) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u8))) - if (handler->Write8(addr, data)) - return true; - return false; -} - -template <> -bool WriteSpecial<u16>(VAddr addr, const u16 data) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u16))) - if (handler->Write16(addr, data)) - return true; - return false; -} - -template <> -bool WriteSpecial<u32>(VAddr addr, const u32 data) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u32))) - if (handler->Write32(addr, data)) - return true; - return false; -} - -template <> -bool WriteSpecial<u64>(VAddr addr, const u64 data) { - const PageTable& page_table = Core::CurrentProcess()->vm_manager.page_table; - for (const auto& handler : GetSpecialHandlers(page_table, addr, sizeof(u64))) - if (handler->Write64(addr, data)) - return true; - return false; -} - boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) { if (addr == 0) { return 0; diff --git a/src/core/memory.h b/src/core/memory.h index f5bf0141f..e9b8ca873 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -36,7 +36,10 @@ enum class PageType : u8 { Unmapped, /// Page is mapped to regular memory. This is the only type you can get pointers to. Memory, - /// Page is mapped to a memory hook, which intercepts read and write requests. + /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and + /// invalidation + RasterizerCachedMemory, + /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. Special, }; @@ -159,12 +162,13 @@ enum : VAddr { TLS_AREA_VADDR = NEW_LINEAR_HEAP_VADDR_END, TLS_ENTRY_SIZE = 0x200, TLS_AREA_SIZE = 0x10000000, - TLS_ADREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, + TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, /// Application stack - STACK_VADDR = TLS_ADREA_VADDR_END, - STACK_SIZE = 0x10000, - STACK_VADDR_END = STACK_VADDR + STACK_SIZE, + STACK_AREA_VADDR = TLS_AREA_VADDR_END, + STACK_AREA_SIZE = 0x10000000, + STACK_AREA_VADDR_END = STACK_AREA_VADDR + STACK_AREA_SIZE, + DEFAULT_STACK_SIZE = 0x100000, /// Application heap /// Size is confirmed to be a static value on fw 3.0.0 @@ -242,4 +246,24 @@ boost::optional<VAddr> PhysicalToVirtualAddress(PAddr addr); */ u8* GetPhysicalPointer(PAddr address); +enum class FlushMode { + /// Write back modified surfaces to RAM + Flush, + /// Remove region from the cache + Invalidate, + /// Write back modified surfaces to RAM, and also remove them from the cache + FlushAndInvalidate, +}; + +/** + * Mark each page touching the region as cached. + */ +void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached); + +/** + * Flushes and invalidates any externally cached rasterizer resources touching the given virtual + * address region. + */ +void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode); + } // namespace Memory diff --git a/src/core/settings.h b/src/core/settings.h index 6f8cd0f03..2c94caab7 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -105,12 +105,10 @@ static const std::array<const char*, NumAnalogs> mapping = {{ }}; } // namespace NativeAnalog -enum class CpuCore { - Unicorn, - Dynarmic, -}; - struct Values { + // System + bool use_docked_mode; + // Controls std::array<std::string, NativeButton::NumButtons> buttons; std::array<std::string, NativeAnalog::NumAnalogs> analogs; @@ -118,7 +116,7 @@ struct Values { std::string touch_device; // Core - CpuCore cpu_core; + bool use_cpu_jit; // Data Storage bool use_virtual_sd; diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index bea05a09b..cecf0a5cb 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -87,8 +87,8 @@ TelemetrySession::TelemetrySession() { #ifdef ENABLE_WEB_SERVICE if (Settings::values.enable_telemetry) { backend = std::make_unique<WebService::TelemetryJson>( - Settings::values.telemetry_endpoint_url, Settings::values.citra_username, - Settings::values.citra_token); + Settings::values.telemetry_endpoint_url, Settings::values.yuzu_username, + Settings::values.yuzu_token); } else { backend = std::make_unique<Telemetry::NullVisitor>(); } @@ -154,12 +154,13 @@ TelemetrySession::TelemetrySession() { #endif // Log user configuration information - AddField(Telemetry::FieldType::UserConfig, "Core_CpuCore", - static_cast<int>(Settings::values.cpu_core)); + AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit); AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor", Settings::values.resolution_factor); AddField(Telemetry::FieldType::UserConfig, "Renderer_ToggleFramelimit", Settings::values.toggle_framelimit); + AddField(Telemetry::FieldType::UserConfig, "System_UseDockedMode", + Settings::values.use_docked_mode); } TelemetrySession::~TelemetrySession() { diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 550c6ea2d..dbc4f8bd4 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -50,8 +50,8 @@ u64 RegenerateTelemetryId(); /** * Verifies the username and token. - * @param username Citra username to use for authentication. - * @param token Citra token to use for authentication. + * @param username yuzu username to use for authentication. + * @param token yuzu token to use for authentication. * @param func A function that gets exectued when the verification is finished * @returns Future with bool indicating whether the verification succeeded */ |