aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/am/am.cpp2
-rw-r--r--src/core/hle/service/audio/audout_u.cpp24
-rw-r--r--src/core/hle/service/audio/audout_u.h4
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp225
-rw-r--r--src/core/hle/service/filesystem/filesystem.h133
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp125
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h2
-rw-r--r--src/core/hle/service/hid/hid.cpp12
-rw-r--r--src/core/hle/service/nifm/nifm.cpp24
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp19
10 files changed, 123 insertions, 447 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 7bb13c735..a871b3eaa 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -621,7 +621,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
FileSys::Path unused;
- auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData);
+ auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused);
if (savedata.Failed()) {
// Create the save data and return an error indicating that the operation was performed.
FileSystem::FormatFileSystem(FileSystem::Type::SaveData);
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 1b4b649d8..8bf273b22 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -27,12 +27,12 @@ public:
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
{2, &IAudioOut::StopAudioOut, "StopAudioOut"},
- {3, &IAudioOut::AppendAudioOutBuffer, "AppendAudioOutBuffer"},
+ {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"},
{4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
- {5, &IAudioOut::GetReleasedAudioOutBuffer, "GetReleasedAudioOutBuffer"},
+ {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"},
{6, nullptr, "ContainsAudioOutBuffer"},
- {7, nullptr, "AppendAudioOutBufferAuto"},
- {8, nullptr, "GetReleasedAudioOutBufferAuto"},
+ {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
+ {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
{9, nullptr, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{11, nullptr, "FlushAudioOutBuffers"},
@@ -96,7 +96,7 @@ private:
rb.PushCopyObjects(buffer_event);
}
- void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) {
+ void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -107,7 +107,7 @@ private:
rb.Push(RESULT_SUCCESS);
}
- void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) {
+ void GetReleasedAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
// TODO(st4rk): This is how libtransistor currently implements the
@@ -163,7 +163,7 @@ private:
AudioState audio_out_state;
};
-void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
+void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -179,7 +179,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
rb.Push<u32>(1);
}
-void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
+void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
if (!audio_out_interface) {
@@ -196,10 +196,10 @@ void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
}
AudOutU::AudOutU() : ServiceFramework("audout:u") {
- static const FunctionInfo functions[] = {{0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
- {1, &AudOutU::OpenAudioOut, "OpenAudioOut"},
- {2, nullptr, "ListAudioOutsAuto"},
- {3, nullptr, "OpenAudioOutAuto"}};
+ static const FunctionInfo functions[] = {{0, &AudOutU::ListAudioOutsImpl, "ListAudioOuts"},
+ {1, &AudOutU::OpenAudioOutImpl, "OpenAudioOut"},
+ {2, &AudOutU::ListAudioOutsImpl, "ListAudioOutsAuto"},
+ {3, &AudOutU::OpenAudioOutImpl, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index 1f9bb9bcf..847d86aa6 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -22,8 +22,8 @@ public:
private:
std::shared_ptr<IAudioOut> audio_out_interface;
- void ListAudioOuts(Kernel::HLERequestContext& ctx);
- void OpenAudioOut(Kernel::HLERequestContext& ctx);
+ void ListAudioOutsImpl(Kernel::HLERequestContext& ctx);
+ void OpenAudioOutImpl(Kernel::HLERequestContext& ctx);
enum class PcmFormat : u32 {
Invalid = 0,
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 25810c165..f58b518b6 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -2,221 +2,36 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "boost/container/flat_map.hpp"
-#include "common/assert.h"
-#include "common/common_paths.h"
+#include <boost/container/flat_map.hpp>
#include "common/file_util.h"
-#include "core/core.h"
-#include "core/file_sys/errors.h"
#include "core/file_sys/filesystem.h"
-#include "core/file_sys/vfs.h"
-#include "core/file_sys/vfs_offset.h"
-#include "core/file_sys/vfs_real.h"
-#include "core/hle/kernel/process.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"
namespace Service::FileSystem {
-// Size of emulated sd card free space, reported in bytes.
-// Just using 32GB because thats reasonable
-// TODO(DarkLordZach): Eventually make this configurable in settings.
-constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
-
-static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
- const std::string& dir_name) {
- if (dir_name == "." || dir_name == "" || dir_name == "/" || dir_name == "\\")
- return base;
-
- return base->GetDirectoryRelative(dir_name);
-}
-
-VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(FileSys::VirtualDir backing_)
- : backing(backing_) {}
-
-std::string VfsDirectoryServiceWrapper::GetName() const {
- return backing->GetName();
-}
-
-ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const {
- auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- auto file = dir->CreateFile(FileUtil::GetFilename(path));
- if (file == nullptr)
- return ResultCode(-1);
- if (!file->Resize(size))
- return ResultCode(-1);
- return RESULT_SUCCESS;
-}
-
-ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const {
- auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (!backing->DeleteFile(FileUtil::GetFilename(path)))
- return ResultCode(-1);
- return RESULT_SUCCESS;
-}
-
-ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const {
- auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty())
- dir = backing;
- auto new_dir = dir->CreateSubdirectory(FileUtil::GetFilename(path));
- if (new_dir == nullptr)
- return ResultCode(-1);
- return RESULT_SUCCESS;
-}
-
-ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const {
- auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path)))
- return ResultCode(-1);
- return RESULT_SUCCESS;
-}
-
-ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const {
- auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path)))
- return ResultCode(-1);
- return RESULT_SUCCESS;
-}
-
-ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path,
- const std::string& dest_path) const {
- auto src = backing->GetFileRelative(src_path);
- if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) {
- // Use more-optimized vfs implementation rename.
- if (src == nullptr)
- return FileSys::ERROR_PATH_NOT_FOUND;
- if (!src->Rename(FileUtil::GetFilename(dest_path)))
- return ResultCode(-1);
- return RESULT_SUCCESS;
- }
-
- // Move by hand -- TODO(DarkLordZach): Optimize
- auto c_res = CreateFile(dest_path, src->GetSize());
- if (c_res != RESULT_SUCCESS)
- return c_res;
-
- auto dest = backing->GetFileRelative(dest_path);
- ASSERT_MSG(dest != nullptr, "Newly created file with success cannot be found.");
-
- ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(),
- "Could not write all of the bytes but everything else has succeded.");
-
- if (!src->GetContainingDirectory()->DeleteFile(FileUtil::GetFilename(src_path)))
- return ResultCode(-1);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path,
- const std::string& dest_path) const {
- auto src = GetDirectoryRelativeWrapped(backing, src_path);
- if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) {
- // Use more-optimized vfs implementation rename.
- if (src == nullptr)
- return FileSys::ERROR_PATH_NOT_FOUND;
- if (!src->Rename(FileUtil::GetFilename(dest_path)))
- return ResultCode(-1);
- return RESULT_SUCCESS;
- }
-
- // TODO(DarkLordZach): Implement renaming across the tree (move).
- ASSERT_MSG(false,
- "Could not rename directory with path \"{}\" to new path \"{}\" because parent dirs "
- "don't match -- UNIMPLEMENTED",
- src_path, dest_path);
-
- return ResultCode(-1);
-}
-
-ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path,
- FileSys::Mode mode) const {
- auto file = backing->GetFileRelative(path);
- if (file == nullptr)
- return FileSys::ERROR_PATH_NOT_FOUND;
-
- if ((static_cast<u32>(mode) & static_cast<u32>(FileSys::Mode::Append)) != 0) {
- return MakeResult<FileSys::VirtualFile>(
- std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()));
- }
-
- return MakeResult<FileSys::VirtualFile>(file);
-}
-
-ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) {
- auto dir = GetDirectoryRelativeWrapped(backing, path);
- if (dir == nullptr)
- return ResultCode(-1);
- return MakeResult(dir);
-}
-
-u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const {
- if (backing->IsWritable())
- return EMULATED_SD_REPORTED_SIZE;
-
- return 0;
-}
-
-ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
- const std::string& path) const {
- auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (dir == nullptr)
- return ResultCode(-1);
- auto filename = FileUtil::GetFilename(path);
- if (dir->GetFile(filename) != nullptr)
- return MakeResult(FileSys::EntryType::File);
- if (dir->GetSubdirectory(filename) != nullptr)
- return MakeResult(FileSys::EntryType::Directory);
- return ResultCode(-1);
-}
-
-// A deferred filesystem for nand save data.
-// This must be deferred because the directory is dependent on title id, which is not set at
-// registration time.
-struct SaveDataDeferredFilesystem : DeferredFilesystem {
-protected:
- FileSys::VirtualDir CreateFilesystem() override {
- u64 title_id = Core::CurrentProcess()->program_id;
- // TODO(DarkLordZach): Users
- u32 user_id = 0;
- std::string nand_directory = fmt::format(
- "{}save/{:016X}/{:08X}/", FileUtil::GetUserPath(D_NAND_IDX), title_id, user_id);
-
- auto savedata =
- std::make_shared<FileSys::RealVfsDirectory>(nand_directory, FileSys::Mode::Write);
- return savedata;
- }
-};
-
/**
* Map of registered file systems, identified by type. Once an file system is registered here, it
* is never removed until UnregisterFileSystems is called.
*/
-static boost::container::flat_map<Type, std::unique_ptr<DeferredFilesystem>> filesystem_map;
-static FileSys::VirtualFile filesystem_romfs = nullptr;
+static boost::container::flat_map<Type, std::unique_ptr<FileSys::FileSystemFactory>> filesystem_map;
-ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& factory, Type type) {
+ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type) {
auto result = filesystem_map.emplace(type, std::move(factory));
bool inserted = result.second;
ASSERT_MSG(inserted, "Tried to register more than one system with same id code");
auto& filesystem = result.first->second;
- LOG_DEBUG(Service_FS, "Registered file system with id code 0x{:08X}", static_cast<u32>(type));
- return RESULT_SUCCESS;
-}
-
-ResultCode RegisterRomFS(FileSys::VirtualFile filesystem) {
- ASSERT_MSG(filesystem_romfs == nullptr,
- "Tried to register more than one system with same id code");
-
- filesystem_romfs = filesystem;
LOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}", filesystem->GetName(),
- static_cast<u32>(Type::RomFS));
+ static_cast<u32>(type));
return RESULT_SUCCESS;
}
-ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type) {
+ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
+ FileSys::Path& path) {
LOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type));
auto itr = filesystem_map.find(type);
@@ -225,13 +40,7 @@ ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type) {
return ResultCode(-1);
}
- return MakeResult(itr->second->Get());
-}
-
-ResultVal<FileSys::VirtualFile> OpenRomFS() {
- if (filesystem_romfs == nullptr)
- return ResultCode(-1);
- return MakeResult(filesystem_romfs);
+ return itr->second->Open(path);
}
ResultCode FormatFileSystem(Type type) {
@@ -243,21 +52,21 @@ ResultCode FormatFileSystem(Type type) {
return ResultCode(-1);
}
- return itr->second->Get()->GetParentDirectory()->DeleteSubdirectory(
- itr->second->Get()->GetName())
- ? RESULT_SUCCESS
- : ResultCode(-1);
+ FileSys::Path unused;
+ return itr->second->Format(unused);
}
void RegisterFileSystems() {
filesystem_map.clear();
- filesystem_romfs = nullptr;
+ std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX);
- auto sdcard = std::make_shared<FileSys::RealVfsDirectory>(sd_directory, FileSys::Mode::Write);
- RegisterFileSystem(std::make_unique<DeferredFilesystem>(sdcard), Type::SDMC);
- RegisterFileSystem(std::make_unique<SaveDataDeferredFilesystem>(), Type::SaveData);
+ 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 d3de797f1..56d26146e 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -6,8 +6,6 @@
#include <memory>
#include "common/common_types.h"
-#include "core/file_sys/filesystem.h"
-#include "core/file_sys/vfs.h"
#include "core/hle/result.h"
namespace FileSys {
@@ -31,136 +29,12 @@ enum class Type {
SDMC = 3,
};
-// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of
-// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
-// avoids repetitive code.
-class VfsDirectoryServiceWrapper {
-public:
- explicit VfsDirectoryServiceWrapper(FileSys::VirtualDir backing);
-
- /**
- * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
- */
- std::string GetName() const;
-
- /**
- * Create a file specified by its path
- * @param path Path relative to the Archive
- * @param size The size of the new file, filled with zeroes
- * @return Result of the operation
- */
- ResultCode CreateFile(const std::string& path, u64 size) const;
-
- /**
- * Delete a file specified by its path
- * @param path Path relative to the archive
- * @return Result of the operation
- */
- ResultCode DeleteFile(const std::string& path) const;
-
- /**
- * Create a directory specified by its path
- * @param path Path relative to the archive
- * @return Result of the operation
- */
- ResultCode CreateDirectory(const std::string& path) const;
-
- /**
- * Delete a directory specified by its path
- * @param path Path relative to the archive
- * @return Result of the operation
- */
- ResultCode DeleteDirectory(const std::string& path) const;
-
- /**
- * Delete a directory specified by its path and anything under it
- * @param path Path relative to the archive
- * @return Result of the operation
- */
- ResultCode DeleteDirectoryRecursively(const std::string& path) const;
-
- /**
- * Rename a File specified by its path
- * @param src_path Source path relative to the archive
- * @param dest_path Destination path relative to the archive
- * @return Result of the operation
- */
- ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const;
-
- /**
- * Rename a Directory specified by its path
- * @param src_path Source path relative to the archive
- * @param dest_path Destination path relative to the archive
- * @return Result of the operation
- */
- ResultCode RenameDirectory(const std::string& src_path, const std::string& dest_path) const;
-
- /**
- * Open a file specified by its path, using the specified mode
- * @param path Path relative to the archive
- * @param mode Mode to open the file with
- * @return Opened file, or error code
- */
- ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const;
-
- /**
- * Open a directory specified by its path
- * @param path Path relative to the archive
- * @return Opened directory, or error code
- */
- ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path);
-
- /**
- * Get the free space
- * @return The number of free bytes in the archive
- */
- u64 GetFreeSpaceSize() const;
-
- /**
- * Get the type of the specified path
- * @return The type of the specified path or error code
- */
- ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
-
-private:
- FileSys::VirtualDir backing;
-};
-
-// A class that deferres the creation of a filesystem until a later time.
-// This is useful if construction depends on a variable not known when the filesystem is registered.
-// Construct this with a filesystem (VirtualDir) to avoid the deferrence feature or override the
-// CreateFilesystem method which will be called on first use.
-struct DeferredFilesystem {
- DeferredFilesystem() = default;
-
- explicit DeferredFilesystem(FileSys::VirtualDir vfs_directory) : fs(std::move(vfs_directory)) {}
-
- FileSys::VirtualDir Get() {
- if (fs == nullptr)
- fs = CreateFilesystem();
-
- return fs;
- }
-
- virtual ~DeferredFilesystem() = default;
-
-protected:
- virtual FileSys::VirtualDir CreateFilesystem() {
- return fs;
- }
-
-private:
- FileSys::VirtualDir fs;
-};
-
/**
* Registers a FileSystem, instances of which can later be opened using its IdCode.
* @param factory FileSystem backend interface to use
* @param type Type used to access this type of FileSystem
*/
-ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& fs, Type type);
-
-ResultCode RegisterRomFS(FileSys::VirtualFile fs);
+ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type);
/**
* Opens a file system
@@ -168,9 +42,8 @@ ResultCode RegisterRomFS(FileSys::VirtualFile fs);
* @param path Path to the file system, used with Binary paths
* @return FileSys::FileSystemBackend interface to the file system
*/
-ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type);
-
-ResultVal<FileSys::VirtualFile> OpenRomFS();
+ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
+ FileSys::Path& path);
/**
* Formats a file system
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 26e8a8c88..82efe7f7d 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -7,6 +7,7 @@
#include "common/string_util.h"
#include "core/core.h"
#include "core/file_sys/directory.h"
+#include "core/file_sys/errors.h"
#include "core/file_sys/filesystem.h"
#include "core/file_sys/storage.h"
#include "core/hle/ipc_helpers.h"
@@ -19,8 +20,8 @@ namespace Service::FileSystem {
class IStorage final : public ServiceFramework<IStorage> {
public:
- IStorage(FileSys::VirtualFile backend_)
- : ServiceFramework("IStorage"), backend(std::move(backend_)) {
+ IStorage(std::unique_ptr<FileSys::StorageBackend>&& backend)
+ : ServiceFramework("IStorage"), backend(std::move(backend)) {
static const FunctionInfo functions[] = {
{0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"},
{3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, {5, nullptr, "OperateRange"},
@@ -29,7 +30,7 @@ public:
}
private:
- FileSys::VirtualFile backend;
+ std::unique_ptr<FileSys::StorageBackend> backend;
void Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -51,8 +52,8 @@ private:
}
// Read the data from the Storage backend
- std::vector<u8> output = backend->ReadBytes(length, offset);
- auto res = MakeResult<size_t>(output.size());
+ std::vector<u8> output(length);
+ ResultVal<size_t> res = backend->Read(offset, length, output.data());
if (res.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res.Code());
@@ -69,8 +70,8 @@ private:
class IFile final : public ServiceFramework<IFile> {
public:
- explicit IFile(FileSys::VirtualFile backend_)
- : ServiceFramework("IFile"), backend(std::move(backend_)) {
+ 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, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"},
@@ -80,7 +81,7 @@ public:
}
private:
- FileSys::VirtualFile backend;
+ std::unique_ptr<FileSys::StorageBackend> backend;
void Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -103,8 +104,8 @@ private:
}
// Read the data from the Storage backend
- std::vector<u8> output = backend->ReadBytes(length, offset);
- auto res = MakeResult<size_t>(output.size());
+ std::vector<u8> output(length);
+ ResultVal<size_t> res = backend->Read(offset, length, output.data());
if (res.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res.Code());
@@ -139,10 +140,9 @@ private:
return;
}
- std::vector<u8> data = ctx.ReadBuffer();
- data.resize(length);
// Write the data to the Storage backend
- auto res = MakeResult<size_t>(backend->WriteBytes(data, offset));
+ std::vector<u8> data = ctx.ReadBuffer();
+ ResultVal<size_t> res = backend->Write(offset, length, true, data.data());
if (res.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res.Code());
@@ -155,8 +155,7 @@ private:
void Flush(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
-
- // Exists for SDK compatibiltity -- No need to flush file.
+ backend->Flush();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -165,7 +164,7 @@ private:
void SetSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 size = rp.Pop<u64>();
- backend->Resize(size);
+ backend->SetSize(size);
LOG_DEBUG(Service_FS, "called, size={}", size);
IPC::ResponseBuilder rb{ctx, 2};
@@ -182,38 +181,19 @@ private:
}
};
-template <typename T>
-static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data,
- FileSys::EntryType type) {
- for (const auto& new_entry : new_data) {
- FileSys::Entry entry;
- entry.filename[0] = '\0';
- std::strncat(entry.filename, new_entry->GetName().c_str(), FileSys::FILENAME_LENGTH - 1);
- entry.type = type;
- entry.file_size = new_entry->GetSize();
- entries.emplace_back(std::move(entry));
- }
-}
-
class IDirectory final : public ServiceFramework<IDirectory> {
public:
- explicit IDirectory(FileSys::VirtualDir backend_)
- : ServiceFramework("IDirectory"), backend(std::move(backend_)) {
+ 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);
-
- // Build entry index now to save time later.
- BuildEntryIndex(entries, backend->GetFiles(), FileSys::File);
- BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::Directory);
}
private:
- FileSys::VirtualDir backend;
- std::vector<FileSys::Entry> entries;
- u64 next_entry_index = 0;
+ std::unique_ptr<FileSys::DirectoryBackend> backend;
void Read(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -224,31 +204,26 @@ private:
// Calculate how many entries we can fit in the output buffer
u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
- // Cap at total number of entries.
- u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index);
-
// Read the data from the Directory backend
- std::vector<FileSys::Entry> entry_data(entries.begin() + next_entry_index,
- entries.begin() + next_entry_index + actual_entries);
-
- next_entry_index += actual_entries;
+ 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(entry_data.size() * sizeof(FileSys::Entry));
- std::memcpy(output.data(), entry_data.data(), output.size());
+ 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(actual_entries);
+ rb.Push(read_entries);
}
void GetEntryCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
- u64 count = entries.size() - next_entry_index;
+ u64 count = backend->GetEntryCount();
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -258,7 +233,7 @@ private:
class IFileSystem final : public ServiceFramework<IFileSystem> {
public:
- explicit IFileSystem(FileSys::VirtualDir backend)
+ explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend)
: ServiceFramework("IFileSystem"), backend(std::move(backend)) {
static const FunctionInfo functions[] = {
{0, &IFileSystem::CreateFile, "CreateFile"},
@@ -293,7 +268,7 @@ public:
LOG_DEBUG(Service_FS, "called file {} mode 0x{:X} size 0x{:08X}", name, mode, size);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(backend.CreateFile(name, size));
+ rb.Push(backend->CreateFile(name, size));
}
void DeleteFile(Kernel::HLERequestContext& ctx) {
@@ -305,7 +280,7 @@ public:
LOG_DEBUG(Service_FS, "called file {}", name);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(backend.DeleteFile(name));
+ rb.Push(backend->DeleteFile(name));
}
void CreateDirectory(Kernel::HLERequestContext& ctx) {
@@ -317,7 +292,7 @@ public:
LOG_DEBUG(Service_FS, "called directory {}", name);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(backend.CreateDirectory(name));
+ rb.Push(backend->CreateDirectory(name));
}
void RenameFile(Kernel::HLERequestContext& ctx) {
@@ -335,7 +310,7 @@ public:
LOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(backend.RenameFile(src_name, dst_name));
+ rb.Push(backend->RenameFile(src_name, dst_name));
}
void OpenFile(Kernel::HLERequestContext& ctx) {
@@ -348,14 +323,14 @@ public:
LOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode));
- auto result = backend.OpenFile(name, mode);
+ auto result = backend->OpenFile(name, mode);
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
return;
}
- IFile file(result.Unwrap());
+ auto file = std::move(result.Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -373,14 +348,14 @@ public:
LOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags);
- auto result = backend.OpenDirectory(name);
+ auto result = backend->OpenDirectory(name);
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
return;
}
- IDirectory directory(result.Unwrap());
+ auto directory = std::move(result.Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -395,7 +370,7 @@ public:
LOG_DEBUG(Service_FS, "called file {}", name);
- auto result = backend.GetEntryType(name);
+ auto result = backend->GetEntryType(name);
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
@@ -415,7 +390,7 @@ public:
}
private:
- VfsDirectoryServiceWrapper backend;
+ std::unique_ptr<FileSys::FileSystemBackend> backend;
};
FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
@@ -516,7 +491,8 @@ void FSP_SRV::TryLoadRomFS() {
if (romfs) {
return;
}
- auto res = OpenRomFS();
+ FileSys::Path unused;
+ auto res = OpenFileSystem(Type::RomFS, unused);
if (res.Succeeded()) {
romfs = std::move(res.Unwrap());
}
@@ -532,7 +508,8 @@ void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) {
void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
- IFileSystem filesystem(OpenFileSystem(Type::SDMC).Unwrap());
+ FileSys::Path unused;
+ auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -555,11 +532,20 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
- IFileSystem filesystem(OpenFileSystem(Type::SaveData).Unwrap());
+ // TODO(Subv): Read the input parameters and mount the requested savedata instead of always
+ // mounting the current process' savedata.
+ FileSys::Path unused;
+ auto filesystem = OpenFileSystem(Type::SaveData, unused);
+
+ if (filesystem.Failed()) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 0};
+ rb.Push(ResultCode(ErrorModule::FS, FileSys::ErrCodes::SaveDataNotFound));
+ return;
+ }
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
+ rb.PushIpcInterface<IFileSystem>(std::move(filesystem.Unwrap()));
}
void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
@@ -582,11 +568,18 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
return;
}
- IStorage storage(romfs);
+ // Attempt to open a StorageBackend interface to the RomFS
+ auto storage = romfs->OpenFile({}, {});
+ if (storage.Failed()) {
+ LOG_CRITICAL(Service_FS, "no storage interface available!");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(storage.Code());
+ return;
+ }
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<IStorage>(std::move(storage));
+ rb.PushIpcInterface<IStorage>(std::move(storage.Unwrap()));
}
void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index b1ef6397f..acb78fac1 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -29,7 +29,7 @@ private:
void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
void OpenRomStorage(Kernel::HLERequestContext& ctx);
- FileSys::VirtualFile romfs;
+ std::unique_ptr<FileSys::FileSystemBackend> romfs;
};
} // namespace Service::FileSystem
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ebb8d13e6..b0f4a384e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -75,7 +75,7 @@ private:
// Set up controllers as neon red+blue Joy-Con attached to console
ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header;
- controller_header.type = ControllerType_Handheld | ControllerType_JoyconPair;
+ controller_header.type = ControllerType_Handheld;
controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent;
controller_header.right_color_body = JOYCON_BODY_NEON_RED;
controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED;
@@ -84,23 +84,21 @@ private:
for (size_t controller = 0; controller < mem.controllers.size(); controller++) {
for (int index = 0; index < HID_NUM_LAYOUTS; index++) {
- // TODO(DarkLordZach): Is this layout/controller config actually invalid?
- if (controller == Controller_Handheld && index == Layout_Single)
- continue;
-
ControllerLayout& layout = mem.controllers[controller].layouts[index];
layout.header.num_entries = HID_NUM_ENTRIES;
layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
// HID shared memory stores the state of the past 17 samples in a circlular buffer,
// each with a timestamp in number of samples since boot.
+ const ControllerInputEntry& last_entry = layout.entries[layout.header.latest_entry];
+
layout.header.timestamp_ticks = CoreTiming::GetTicks();
layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES;
ControllerInputEntry& entry = layout.entries[layout.header.latest_entry];
- entry.timestamp++;
+ entry.timestamp = last_entry.timestamp + 1;
// TODO(shinyquagsire23): Is this always identical to timestamp?
- entry.timestamp_2++;
+ entry.timestamp_2 = entry.timestamp;
// TODO(shinyquagsire23): More than just handheld input
if (controller != Controller_Handheld)
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 54a151c26..0d951084b 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -148,6 +148,24 @@ private:
LOG_DEBUG(Service_NIFM, "called");
}
+ void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_NIFM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u8>(0);
+ }
+ void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_NIFM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u8>(0);
+ }
+ void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_NIFM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u8>(0);
+ }
};
IGeneralService::IGeneralService() : ServiceFramework("IGeneralService") {
@@ -167,11 +185,11 @@ IGeneralService::IGeneralService() : ServiceFramework("IGeneralService") {
{14, &IGeneralService::CreateTemporaryNetworkProfile, "CreateTemporaryNetworkProfile"},
{15, nullptr, "GetCurrentIpConfigInfo"},
{16, nullptr, "SetWirelessCommunicationEnabled"},
- {17, nullptr, "IsWirelessCommunicationEnabled"},
+ {17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
{18, nullptr, "GetInternetConnectionStatus"},
{19, nullptr, "SetEthernetCommunicationEnabled"},
- {20, nullptr, "IsEthernetCommunicationEnabled"},
- {21, nullptr, "IsAnyInternetRequestAccepted"},
+ {20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
+ {21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},
{22, nullptr, "IsAnyForegroundRequestAccepted"},
{23, nullptr, "PutToSleep"},
{24, nullptr, "WakeUp"},
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 303acdcb3..671b092e1 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -29,24 +29,9 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) {
IocGetConfigParams params{};
std::memcpy(&params, input.data(), sizeof(params));
- LOG_DEBUG(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
+ LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
params.param_str.data());
-
- if (!strcmp(params.domain_str.data(), "nv")) {
- if (!strcmp(params.param_str.data(), "NV_MEMORY_PROFILER")) {
- params.config_str[0] = '0';
- } else if (!strcmp(params.param_str.data(), "NVN_THROUGH_OPENGL")) {
- params.config_str[0] = '0';
- } else if (!strcmp(params.param_str.data(), "NVRM_GPU_PREVENT_USE")) {
- params.config_str[0] = '0';
- } else {
- params.config_str[0] = '\0';
- }
- } else {
- UNIMPLEMENTED(); // unknown domain? Only nv has been seen so far on hardware
- }
- std::memcpy(output.data(), &params, sizeof(params));
- return 0;
+ return 0x30006; // Returns error on production mode
}
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,