summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/kernel.cpp1
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/result.h2
-rw-r--r--src/core/hle/service/fs/archive.cpp51
-rw-r--r--src/core/hle/service/fs/archive.h6
-rw-r--r--src/core/hle/service/fs/fs_user.cpp42
6 files changed, 95 insertions, 13 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 929422b36..6a690e915 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -14,6 +14,7 @@ namespace Kernel {
Handle g_main_thread = 0;
ObjectPool g_object_pool;
+u64 g_program_id = 0;
ObjectPool::ObjectPool() {
next_id = INITIAL_NEXT_ID;
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7e0f15c84..7123485be 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -151,6 +151,12 @@ private:
extern ObjectPool g_object_pool;
extern Handle g_main_thread;
+/// The ID code of the currently running game
+/// TODO(Subv): This variable should not be here,
+/// we need a way to store information about the currently loaded application
+/// for later query during runtime, maybe using the LDR service?
+extern u64 g_program_id;
+
/// Initialize the kernel
void Init();
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 15c4a2677..14d2be4a2 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -17,6 +17,8 @@
/// Detailed description of the error. This listing is likely incomplete.
enum class ErrorDescription : u32 {
Success = 0,
+ FS_NotFound = 100,
+ FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
InvalidSection = 1000,
TooLarge = 1001,
NotAuthorized = 1002,
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index caf82d556..9c3834733 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -9,6 +9,7 @@
#include "common/file_util.h"
#include "common/math_util.h"
+#include "core/file_sys/archive_savedata.h"
#include "core/file_sys/archive_backend.h"
#include "core/file_sys/archive_sdmc.h"
#include "core/file_sys/directory_backend.h"
@@ -135,6 +136,13 @@ public:
break;
}
+ case FileCommand::Flush:
+ {
+ LOG_TRACE(Service_FS, "Flush");
+ backend->Flush();
+ break;
+ }
+
// Unknown command...
default:
LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
@@ -220,9 +228,18 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) {
auto itr = id_code_map.find(id_code);
if (itr == id_code_map.end()) {
+ if (id_code == ArchiveIdCode::SaveData) {
+ // When a SaveData archive is created for the first time, it is not yet formatted
+ // and the save file/directory structure expected by the game has not yet been initialized.
+ // Returning the NotFormatted error code will signal the game to provision the SaveData archive
+ // with the files and folders that it expects.
+ // The FormatSaveData service call will create the SaveData archive when it is called.
+ return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
+ ErrorSummary::InvalidState, ErrorLevel::Status);
+ }
// TODO: Verify error against hardware
return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
- ErrorSummary::NotFound, ErrorLevel::Permanent);
+ ErrorSummary::NotFound, ErrorLevel::Permanent);
}
// This should never even happen in the first place with 64-bit handles,
@@ -260,8 +277,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode);
if (backend == nullptr) {
- return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
- ErrorSummary::NotFound, ErrorLevel::Permanent);
+ return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS,
+ ErrorSummary::NotFound, ErrorLevel::Status);
}
auto file = std::make_unique<File>(std::move(backend), path);
@@ -366,6 +383,28 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
return MakeResult<Handle>(handle);
}
+ResultCode FormatSaveData() {
+ // TODO(Subv): Actually wipe the savedata folder after creating or opening it
+
+ // Do not create the archive again if it already exists
+ if (id_code_map.find(ArchiveIdCode::SaveData) != id_code_map.end())
+ return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the correct error code
+
+ // Create the SaveData archive
+ std::string savedata_directory = FileUtil::GetUserPath(D_SAVEDATA_IDX);
+ auto savedata_archive = std::make_unique<FileSys::Archive_SaveData>(savedata_directory,
+ Kernel::g_program_id);
+
+ if (savedata_archive->Initialize()) {
+ CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData);
+ return RESULT_SUCCESS;
+ } else {
+ LOG_ERROR(Service_FS, "Can't instantiate SaveData archive with path %s",
+ savedata_archive->GetMountPoint().c_str());
+ return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the proper error code
+ }
+}
+
/// Initialize archives
void ArchiveInit() {
next_handle = 1;
@@ -375,9 +414,9 @@ void ArchiveInit() {
// archive type is SDMC, so it is the only one getting exposed.
std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX);
- auto archive = std::make_unique<FileSys::Archive_SDMC>(sdmc_directory);
- if (archive->Initialize())
- CreateArchive(std::move(archive), ArchiveIdCode::SDMC);
+ auto sdmc_archive = std::make_unique<FileSys::Archive_SDMC>(sdmc_directory);
+ if (sdmc_archive->Initialize())
+ CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC);
else
LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str());
}
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index a38de92e3..a128276b6 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -109,6 +109,12 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
*/
ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
+/**
+ * Creates a blank SaveData archive.
+ * @return ResultCode 0 on success or the corresponding code on error
+ */
+ResultCode FormatSaveData();
+
/// Initialize archives
void ArchiveInit();
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 0f75d5e3a..f99d84b2f 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -3,11 +3,11 @@
// Refer to the license.txt file included.
#include "common/common.h"
+#include "common/file_util.h"
#include "common/scope_exit.h"
-
#include "common/string_util.h"
-#include "core/hle/service/fs/archive.h"
#include "core/hle/result.h"
+#include "core/hle/service/fs/archive.h"
#include "core/hle/service/fs/fs_user.h"
#include "core/settings.h"
@@ -50,9 +50,7 @@ static void Initialize(Service::Interface* self) {
static void OpenFile(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to
- // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
- Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
+ ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
u32 filename_size = cmd_buff[5];
FileSys::Mode mode; mode.hex = cmd_buff[6];
@@ -398,6 +396,36 @@ static void IsSdmcDetected(Service::Interface* self) {
LOG_DEBUG(Service_FS, "called");
}
+/**
+ * FS_User::FormatSaveData service function
+ * Inputs:
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void FormatSaveData(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ LOG_DEBUG(Service_FS, "(STUBBED)");
+
+ // TODO(Subv): Find out what the inputs and outputs of this function are
+
+ cmd_buff[1] = FormatSaveData().raw;
+}
+
+/**
+ * FS_User::FormatThisUserSaveData service function
+ * Inputs:
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void FormatThisUserSaveData(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ LOG_DEBUG(Service_FS, "(STUBBED)");
+
+ // TODO(Subv): Find out what the inputs and outputs of this function are
+
+ cmd_buff[1] = FormatSaveData().raw;
+}
+
const FSUserInterface::FunctionInfo FunctionTable[] = {
{0x000100C6, nullptr, "Dummy1"},
{0x040100C4, nullptr, "Control"},
@@ -415,7 +443,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
{0x080C00C2, OpenArchive, "OpenArchive"},
{0x080D0144, nullptr, "ControlArchive"},
{0x080E0080, CloseArchive, "CloseArchive"},
- {0x080F0180, nullptr, "FormatThisUserSaveData"},
+ {0x080F0180, FormatThisUserSaveData,"FormatThisUserSaveData"},
{0x08100200, nullptr, "CreateSystemSaveData"},
{0x08110040, nullptr, "DeleteSystemSaveData"},
{0x08120080, nullptr, "GetFreeBytes"},
@@ -476,7 +504,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = {
{0x08490040, nullptr, "GetArchiveResource"},
{0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
{0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
- {0x084C0242, nullptr, "FormatSaveData"},
+ {0x084C0242, FormatSaveData, "FormatSaveData"},
{0x084D0102, nullptr, "GetLegacySubBannerData"},
{0x084E0342, nullptr, "UpdateSha256Context"},
{0x084F0102, nullptr, "ReadSpecialFile"},