diff options
Diffstat (limited to 'src/core/hle/service')
-rw-r--r-- | src/core/hle/service/cfg/cfg_u.cpp | 66 | ||||
-rw-r--r-- | src/core/hle/service/dsp_dsp.cpp | 66 | ||||
-rw-r--r-- | src/core/hle/service/fs/archive.cpp | 191 | ||||
-rw-r--r-- | src/core/hle/service/fs/archive.h | 45 | ||||
-rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/service/ldr_ro.cpp | 64 | ||||
-rw-r--r-- | src/core/hle/service/ptm_u.cpp | 35 |
7 files changed, 325 insertions, 152 deletions
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index 1da9f59f6..5aa53cf75 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp @@ -5,6 +5,7 @@ #include "common/file_util.h" #include "common/log.h" #include "common/string_util.h" +#include "core/settings.h" #include "core/file_sys/archive_systemsavedata.h" #include "core/hle/hle.h" #include "core/hle/service/cfg/cfg.h" @@ -129,6 +130,65 @@ static void GetConfigInfoBlk2(Service::Interface* self) { } /** + * CFG_User::SecureInfoGetRegion service function + * Inputs: + * 1 : None + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Region value loaded from SecureInfo offset 0x100 + */ +static void SecureInfoGetRegion(Service::Interface* self) { + u32* cmd_buffer = Kernel::GetCommandBuffer(); + + cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error + cmd_buffer[2] = Settings::values.region_value; +} + +/** + * CFG_User::GenHashConsoleUnique service function + * Inputs: + * 1 : 20 bit application ID salt + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Hash/"ID" lower word + * 3 : Hash/"ID" upper word + */ +static void GenHashConsoleUnique(Service::Interface* self) { + u32* cmd_buffer = Kernel::GetCommandBuffer(); + u32 app_id_salt = cmd_buffer[1]; + + cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error + cmd_buffer[2] = 0x33646D6F ^ (app_id_salt & 0xFFFFF); // 3dmoo hash + cmd_buffer[3] = 0x6F534841 ^ (app_id_salt & 0xFFFFF); + + LOG_WARNING(Service_CFG, "(STUBBED) called app_id_salt=0x%08X", app_id_salt); +} + +/** + * CFG_User::GetRegionCanadaUSA service function + * Inputs: + * 1 : None + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Output value + */ +static void GetRegionCanadaUSA(Service::Interface* self) { + u32* cmd_buffer = Kernel::GetCommandBuffer(); + + cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error + + u8 canada_or_usa = 1; + if (canada_or_usa == Settings::values.region_value) { + cmd_buffer[2] = 1; + } else { + cmd_buffer[2] = 0; + } +} + +/** * CFG_User::GetSystemModel service function * Inputs: * 0 : 0x00050000 @@ -171,9 +231,9 @@ static void GetModelNintendo2DS(Service::Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, - {0x00020000, nullptr, "SecureInfoGetRegion"}, - {0x00030040, nullptr, "GenHashConsoleUnique"}, - {0x00040000, nullptr, "GetRegionCanadaUSA"}, + {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, + {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, + {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, {0x00050000, GetSystemModel, "GetSystemModel"}, {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 0f86894a6..a720b63f3 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -128,6 +128,31 @@ void WriteReg0x10(Service::Interface* self) { } /** + * DSP_DSP::WriteProcessPipe service function + * Inputs: + * 1 : Number + * 2 : Size + * 3 : (size <<14) | 0x402 + * 4 : Buffer + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +void WriteProcessPipe(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + u32 number = cmd_buff[1]; + u32 size = cmd_buff[2]; + u32 new_size = cmd_buff[3]; + u32 buffer = cmd_buff[4]; + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + + LOG_WARNING(Service_DSP, "(STUBBED) called number=%u, size=0x%08X, new_size=0x%08X, buffer=0x%08X", + number, size, new_size, buffer); +} + +/** * DSP_DSP::ReadPipeIfPossible service function * Inputs: * 1 : Unknown @@ -169,6 +194,41 @@ void ReadPipeIfPossible(Service::Interface* self) { LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%08X, buffer=0x%08X", size, addr); } +/** + * DSP_DSP::SetSemaphoreMask service function + * Inputs: + * 1 : Mask + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void SetSemaphoreMask(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + u32 mask = cmd_buff[1]; + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + + LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x%08X", mask); +} + +/** + * DSP_DSP::GetHeadphoneStatus service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : The headphone status response, 0 = Not using headphones?, + * 1 = using headphones? + */ +void GetHeadphoneStatus(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[2] = 0; // Not using headphones? + + LOG_WARNING(Service_DSP, "(STUBBED) called"); +} + const Interface::FunctionInfo FunctionTable[] = { {0x00010040, nullptr, "RecvData"}, {0x00020040, nullptr, "RecvDataIsReady"}, @@ -179,7 +239,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00090040, nullptr, "ClearSemaphore"}, {0x000B0000, nullptr, "CheckSemaphoreRequest"}, {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, - {0x000D0082, nullptr, "WriteProcessPipe"}, + {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, {0x001100C2, LoadComponent, "LoadComponent"}, {0x00120000, nullptr, "UnloadComponent"}, @@ -187,13 +247,13 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00140082, nullptr, "InvalidateDCache"}, {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, - {0x00170040, nullptr, "SetSemaphoreMask"}, + {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"}, {0x00180040, nullptr, "GetPhysicalAddress"}, {0x00190040, nullptr, "GetVirtualAddress"}, {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, {0x001C0082, nullptr, "SetIirFilterEQ"}, - {0x001F0000, nullptr, "GetHeadphoneStatus"}, + {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"}, {0x00210000, nullptr, "GetIsDspOccupied"}, }; diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index ccf132f31..e197d3599 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -5,6 +5,8 @@ #include <memory> #include <unordered_map> +#include <boost/container/flat_map.hpp> + #include "common/common_types.h" #include "common/file_util.h" #include "common/make_unique.h" @@ -18,7 +20,6 @@ #include "core/file_sys/archive_sdmc.h" #include "core/file_sys/directory_backend.h" #include "core/hle/service/fs/archive.h" -#include "core/hle/kernel/session.h" #include "core/hle/result.h" // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. @@ -74,43 +75,19 @@ enum class DirectoryCommand : u32 { Close = 0x08020000, }; -class Archive { -public: - Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) - : id_code(id_code), backend(std::move(backend)) { - } - - std::string GetName() const { return "Archive: " + backend->GetName(); } - - ArchiveIdCode id_code; ///< Id code of the archive - std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface -}; - -class File : public Kernel::Session { -public: - File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) - : path(path), priority(0), backend(std::move(backend)) { - } - - std::string GetName() const override { return "Path: " + path.DebugStr(); } - - FileSys::Path path; ///< Path of the file - u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means - std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface - - ResultVal<bool> SyncRequest() override { - u32* cmd_buff = Kernel::GetCommandBuffer(); - FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); - switch (cmd) { +ResultVal<bool> File::SyncRequest() { + u32* cmd_buff = Kernel::GetCommandBuffer(); + FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); + switch (cmd) { // Read from file... case FileCommand::Read: { - u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; - u32 length = cmd_buff[3]; + u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; + u32 length = cmd_buff[3]; u32 address = cmd_buff[5]; LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", - GetTypeName().c_str(), GetName().c_str(), offset, length, address); + GetTypeName().c_str(), GetName().c_str(), offset, length, address); cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); break; } @@ -118,12 +95,12 @@ public: // Write to file... case FileCommand::Write: { - u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; - u32 length = cmd_buff[3]; - u32 flush = cmd_buff[4]; + u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; + u32 length = cmd_buff[3]; + u32 flush = cmd_buff[4]; u32 address = cmd_buff[6]; LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", - GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); + GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); break; } @@ -141,7 +118,7 @@ public: { u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", - GetTypeName().c_str(), GetName().c_str(), size); + GetTypeName().c_str(), GetName().c_str(), size); backend->SetSize(size); break; } @@ -187,27 +164,15 @@ public: ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. return error; - } - cmd_buff[1] = 0; // No error - return MakeResult<bool>(false); } -}; - -class Directory : public Kernel::Session { -public: - Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) - : path(path), backend(std::move(backend)) { - } - - std::string GetName() const override { return "Directory: " + path.DebugStr(); } - - FileSys::Path path; ///< Path of the directory - std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + return MakeResult<bool>(false); +} - ResultVal<bool> SyncRequest() override { - u32* cmd_buff = Kernel::GetCommandBuffer(); - DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); - switch (cmd) { +ResultVal<bool> Directory::SyncRequest() { + u32* cmd_buff = Kernel::GetCommandBuffer(); + DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); + switch (cmd) { // Read from directory... case DirectoryCommand::Read: @@ -216,7 +181,7 @@ public: u32 address = cmd_buff[3]; auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); LOG_TRACE(Service_FS, "Read %s %s: count=%d", - GetTypeName().c_str(), GetName().c_str(), count); + GetTypeName().c_str(), GetName().c_str(), count); // Number of entries actually read cmd_buff[2] = backend->Read(count, entries); @@ -236,29 +201,31 @@ public: ResultCode error = UnimplementedFunction(ErrorModule::FS); cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. return MakeResult<bool>(false); - } - cmd_buff[1] = 0; // No error - return MakeResult<bool>(false); } -}; + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + return MakeResult<bool>(false); +} //////////////////////////////////////////////////////////////////////////////////////////////////// +using FileSys::ArchiveBackend; +using FileSys::ArchiveFactory; + /** * Map of registered archives, identified by id code. Once an archive is registered here, it is * never removed until the FS service is shut down. */ -static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map; +static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map; /** * Map of active archive handles. Values are pointers to the archives in `idcode_map`. */ -static std::unordered_map<ArchiveHandle, Archive*> handle_map; +static std::unordered_map<ArchiveHandle, std::unique_ptr<ArchiveBackend>> handle_map; static ArchiveHandle next_handle; -static Archive* GetArchive(ArchiveHandle handle) { +static ArchiveBackend* GetArchive(ArchiveHandle handle) { auto itr = handle_map.find(handle); - return (itr == handle_map.end()) ? nullptr : itr->second; + return (itr == handle_map.end()) ? nullptr : itr->second.get(); } ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { @@ -271,15 +238,13 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi ErrorSummary::NotFound, ErrorLevel::Permanent); } - ResultCode res = itr->second->backend->Open(archive_path); - if (!res.IsSuccess()) - return res; + CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); // This should never even happen in the first place with 64-bit handles, while (handle_map.count(next_handle) != 0) { ++next_handle; } - handle_map.emplace(next_handle, itr->second.get()); + handle_map.emplace(next_handle, std::move(res)); return MakeResult<ArchiveHandle>(next_handle++); } @@ -292,39 +257,39 @@ ResultCode CloseArchive(ArchiveHandle handle) { // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 -ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { - auto result = id_code_map.emplace(id_code, Common::make_unique<Archive>(std::move(backend), id_code)); +ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { + auto result = id_code_map.emplace(id_code, std::move(factory)); bool inserted = result.second; - _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); + _assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); auto& archive = result.first->second; LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); return RESULT_SUCCESS; } -ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, +ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { - Archive* archive = GetArchive(archive_handle); + ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; - std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); + std::unique_ptr<FileSys::FileBackend> backend = archive->OpenFile(path, mode); if (backend == nullptr) { return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); } auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path)); - return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file)); + return MakeResult<Kernel::SharedPtr<File>>(std::move(file)); } ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { - Archive* archive = GetArchive(archive_handle); + ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; - if (archive->backend->DeleteFile(path)) + if (archive->DeleteFile(path)) return RESULT_SUCCESS; return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description ErrorSummary::Canceled, ErrorLevel::Status); @@ -332,13 +297,13 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { - Archive* src_archive = GetArchive(src_archive_handle); - Archive* dest_archive = GetArchive(dest_archive_handle); + ArchiveBackend* src_archive = GetArchive(src_archive_handle); + ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) return ERR_INVALID_HANDLE; if (src_archive == dest_archive) { - if (src_archive->backend->RenameFile(src_path, dest_path)) + if (src_archive->RenameFile(src_path, dest_path)) return RESULT_SUCCESS; } else { // TODO: Implement renaming across archives @@ -352,30 +317,30 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil } ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { - Archive* archive = GetArchive(archive_handle); + ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; - if (archive->backend->DeleteDirectory(path)) + if (archive->DeleteDirectory(path)) return RESULT_SUCCESS; return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description ErrorSummary::Canceled, ErrorLevel::Status); } ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { - Archive* archive = GetArchive(archive_handle); + ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; - return archive->backend->CreateFile(path, file_size); + return archive->CreateFile(path, file_size); } ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { - Archive* archive = GetArchive(archive_handle); + ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; - if (archive->backend->CreateDirectory(path)) + if (archive->CreateDirectory(path)) return RESULT_SUCCESS; return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description ErrorSummary::Canceled, ErrorLevel::Status); @@ -383,13 +348,13 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { - Archive* src_archive = GetArchive(src_archive_handle); - Archive* dest_archive = GetArchive(dest_archive_handle); + ArchiveBackend* src_archive = GetArchive(src_archive_handle); + ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) return ERR_INVALID_HANDLE; if (src_archive == dest_archive) { - if (src_archive->backend->RenameDirectory(src_path, dest_path)) + if (src_archive->RenameDirectory(src_path, dest_path)) return RESULT_SUCCESS; } else { // TODO: Implement renaming across archives @@ -402,31 +367,29 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons ErrorSummary::NothingHappened, ErrorLevel::Status); } -ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, +ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { - Archive* archive = GetArchive(archive_handle); + ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; - std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); + std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); if (backend == nullptr) { return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Permanent); } auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); - return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory)); + return MakeResult<Kernel::SharedPtr<Directory>>(std::move(directory)); } -ResultCode FormatSaveData() { - // Do not create the archive again if it already exists - auto archive_itr = id_code_map.find(ArchiveIdCode::SaveData); +ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) { + auto archive_itr = id_code_map.find(id_code); if (archive_itr == id_code_map.end()) { return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error } - // Use an empty path, we do not use it when formatting the savedata - return archive_itr->second->backend->Format(FileSys::Path()); + return archive_itr->second->Format(path); } ResultCode CreateExtSaveData(u32 high, u32 low) { @@ -460,32 +423,32 @@ void ArchiveInit() { std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); - auto sdmc_archive = Common::make_unique<FileSys::Archive_SDMC>(sdmc_directory); - if (sdmc_archive->Initialize()) - CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC); + auto sdmc_factory = Common::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory); + if (sdmc_factory->Initialize()) + RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); else LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); // Create the SaveData archive - auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(sdmc_directory); - CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); + auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); + RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); - auto extsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(sdmc_directory, false); - if (extsavedata_archive->Initialize()) - CreateArchive(std::move(extsavedata_archive), ArchiveIdCode::ExtSaveData); + auto extsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); + if (extsavedata_factory->Initialize()) + RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); else - LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_archive->GetMountPoint().c_str()); + LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); - auto sharedextsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); - if (sharedextsavedata_archive->Initialize()) - CreateArchive(std::move(sharedextsavedata_archive), ArchiveIdCode::SharedExtSaveData); + auto sharedextsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); + if (sharedextsavedata_factory->Initialize()) + RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); else LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", - sharedextsavedata_archive->GetMountPoint().c_str()); + sharedextsavedata_factory->GetMountPoint().c_str()); // Create the SaveDataCheck archive, basically a small variation of the RomFS archive - auto savedatacheck_archive = Common::make_unique<FileSys::Archive_SaveDataCheck>(nand_directory); - CreateArchive(std::move(savedatacheck_archive), ArchiveIdCode::SaveDataCheck); + auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); + RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); } /// Shutdown archives diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index ab5ea4da8..c490327d0 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -8,6 +8,7 @@ #include "core/file_sys/archive_backend.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/session.h" #include "core/hle/result.h" /// The unique system identifier hash, also known as ID0 @@ -36,6 +37,35 @@ enum class ArchiveIdCode : u32 { typedef u64 ArchiveHandle; +class File : public Kernel::Session { +public: + File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) + : path(path), priority(0), backend(std::move(backend)) { + } + + std::string GetName() const override { return "Path: " + path.DebugStr(); } + + FileSys::Path path; ///< Path of the file + u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means + std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface + + ResultVal<bool> SyncRequest() override; +}; + +class Directory : public Kernel::Session { +public: + Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) + : path(path), backend(std::move(backend)) { + } + + std::string GetName() const override { return "Directory: " + path.DebugStr(); } + + FileSys::Path path; ///< Path of the directory + std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface + + ResultVal<bool> SyncRequest() override; +}; + /** * Opens an archive * @param id_code IdCode of the archive to open @@ -51,11 +81,11 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi ResultCode CloseArchive(ArchiveHandle handle); /** - * Creates an Archive + * Registers an Archive type, instances of which can later be opened using its IdCode. * @param backend File system backend interface to the archive * @param id_code Id code used to access this type of archive */ -ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); +ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); /** * Open a File from an Archive @@ -64,7 +94,7 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc * @param mode Mode under which to open the File * @return The opened File object as a Session */ -ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, +ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); /** @@ -128,14 +158,17 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons * @param path Path to the Directory inside of the Archive * @return The opened Directory object as a Session */ -ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, +ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); /** - * Creates a blank SaveData archive. + * Erases the contents of the physical folder that contains the archive + * identified by the specified id code and path + * @param id_code The id of the archive to format + * @param path The path to the archive, if relevant. * @return ResultCode 0 on success or the corresponding code on error */ -ResultCode FormatSaveData(); +ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = FileSys::Path()); /** * Creates a blank SharedExtSaveData archive for the specified extdata ID diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 94a3a31c8..71ee4ff55 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -61,7 +61,7 @@ static void OpenFile(Service::Interface* self) { LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); - ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); + ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); @@ -117,7 +117,7 @@ static void OpenFileDirectly(Service::Interface* self) { } SCOPE_EXIT({ CloseArchive(*archive_handle); }); - ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); + ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); cmd_buff[1] = file_res.Code().raw; if (file_res.Succeeded()) { cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); @@ -337,7 +337,7 @@ static void OpenDirectory(Service::Interface* self) { LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); - ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); + ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); cmd_buff[1] = dir_res.Code().raw; if (dir_res.Succeeded()) { cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); @@ -468,7 +468,7 @@ static void FormatSaveData(Service::Interface* self) { return; } - cmd_buff[1] = FormatSaveData().raw; + cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; } /** @@ -484,7 +484,7 @@ static void FormatThisUserSaveData(Service::Interface* self) { // TODO(Subv): Find out what the inputs and outputs of this function are - cmd_buff[1] = FormatSaveData().raw; + cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; } static void CreateExtSaveData(Service::Interface* self) { diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp index 459717fff..ea96f64af 100644 --- a/src/core/hle/service/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro.cpp @@ -11,9 +11,69 @@ namespace LDR_RO { +/** + * LDR_RO::Initialize service function + * Inputs: + * 1 : CRS buffer pointer + * 2 : CRS Size + * 3 : Process memory address where the CRS will be mapped + * 4 : Value, must be zero + * 5 : KProcess handle + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +static void Initialize(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 crs_buffer_ptr = cmd_buff[1]; + u32 crs_size = cmd_buff[2]; + u32 address = cmd_buff[3]; + u32 value = cmd_buff[4]; + u32 process = cmd_buff[5]; + + if (value != 0) { + LOG_ERROR(Service_LDR, "This value should be zero, but is actually %u!", value); + } + + // TODO(purpasmart96): Verify return header on HW + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + + LOG_WARNING(Service_LDR, "(STUBBED) called"); +} + +/** + * LDR_RO::LoadCRR service function + * Inputs: + * 1 : CRS buffer pointer + * 2 : CRS Size + * 3 : Value, must be zero + * 4 : KProcess handle + * Outputs: + * 0 : Return header + * 1 : Result of function, 0 on success, otherwise error code + */ +static void LoadCRR(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 crs_buffer_ptr = cmd_buff[1]; + u32 crs_size = cmd_buff[2]; + u32 value = cmd_buff[3]; + u32 process = cmd_buff[4]; + + if (value != 0) { + LOG_ERROR(Service_LDR, "This value should be zero, but is actually %u!", value); + } + + // TODO(purpasmart96): Verify return header on HW + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + + LOG_WARNING(Service_LDR, "(STUBBED) called"); +} + const Interface::FunctionInfo FunctionTable[] = { - {0x000100C2, nullptr, "Initialize"}, - {0x00020082, nullptr, "LoadCRR"}, + {0x000100C2, Initialize, "Initialize"}, + {0x00020082, LoadCRR, "LoadCRR"}, {0x00030042, nullptr, "UnloadCCR"}, {0x000402C2, nullptr, "LoadExeCRO"}, {0x000500C2, nullptr, "LoadCROSymbols"}, diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index 7b465a348..7c8d9ce8c 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp @@ -4,8 +4,9 @@ #include "common/log.h" #include "common/make_unique.h" -#include "core/file_sys/archive_extsavedata.h" + #include "core/hle/hle.h" +#include "core/hle/service/fs/archive.h" #include "core/hle/service/ptm_u.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -28,7 +29,6 @@ struct GameCoin { u8 day; }; static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; -static std::unique_ptr<FileSys::Archive_ExtSaveData> ptm_shared_extsavedata; static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; /// Charge levels used by PTM functions @@ -138,31 +138,28 @@ const Interface::FunctionInfo FunctionTable[] = { Interface::Interface() { Register(FunctionTable); - // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file - // TODO(Subv): In the future we should use the FS service to query this archive - std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); - ptm_shared_extsavedata = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); - if (!ptm_shared_extsavedata->Initialize()) { - LOG_CRITICAL(Service_PTM, "Could not initialize SharedExtSaveData archive for the PTM:U service"); - return; - } + + // Open the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file FileSys::Path archive_path(ptm_shared_extdata_id); - ResultCode result = ptm_shared_extsavedata->Open(archive_path); + auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); // If the archive didn't exist, create the files inside - if (result.description == ErrorDescription::FS_NotFormatted) { - // Format the archive to clear the directories - ptm_shared_extsavedata->Format(archive_path); + if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { + // Format the archive to create the directories + Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); // Open it again to get a valid archive now that the folder exists - ptm_shared_extsavedata->Open(archive_path); + archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); + _assert_msg_(Service_PTM, archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); + FileSys::Path gamecoin_path("gamecoin.dat"); FileSys::Mode open_mode = {}; open_mode.write_flag = 1; open_mode.create_flag = 1; // Open the file and write the default gamecoin information - auto gamecoin = ptm_shared_extsavedata->OpenFile(gamecoin_path, open_mode); - if (gamecoin != nullptr) { - gamecoin->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); - gamecoin->Close(); + auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); + if (gamecoin_result.Succeeded()) { + auto gamecoin = gamecoin_result.MoveFrom(); + gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); + gamecoin->backend->Close(); } } } |