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   */ | 
