From 66c1db72887b6bd94c14cb63256a1aff8f4d76a3 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Mon, 1 Jun 2015 21:26:40 -0500
Subject: [PATCH] ExtSavedata: Save the icon passed to CreateExtSaveData to the
 correct folder.

Organize the ExtSaveData folders as they are stored in the console.
---
 src/core/file_sys/archive_extsavedata.cpp |  9 ++++++---
 src/core/hle/service/fs/archive.cpp       | 23 ++++++++++++++++++++---
 src/core/hle/service/fs/archive.h         |  4 +++-
 src/core/hle/service/fs/fs_user.cpp       | 16 +++++++++-------
 4 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 975aafb356..e50c58a52f 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -71,7 +71,7 @@ bool ArchiveFactory_ExtSaveData::Initialize() {
 }
 
 ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) {
-    std::string fullpath = GetExtSaveDataPath(mount_point, path);
+    std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/";
     if (!FileUtil::Exists(fullpath)) {
         // TODO(Subv): Check error code, this one is probably wrong
         return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
@@ -82,8 +82,11 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
 }
 
 ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) {
-    std::string fullpath = GetExtSaveDataPath(mount_point, path);
-    FileUtil::CreateFullPath(fullpath);
+    // These folders are always created with the ExtSaveData
+    std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/";
+    std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/";
+    FileUtil::CreateFullPath(user_path);
+    FileUtil::CreateFullPath(boss_path);
     return RESULT_SUCCESS;
 }
 
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 7cab68024a..4e275cb13a 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -406,7 +406,7 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) {
     return archive_itr->second->Format(path);
 }
 
-ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) {
+ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size) {
     // Construct the binary path to the archive first
     FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
 
@@ -421,9 +421,25 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low) {
     }
 
     std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
-    std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
-    if (!FileUtil::CreateFullPath(extsavedata_path))
+    std::string game_path = FileSys::GetExtSaveDataPath(base_path, path);
+    // These two folders are always created with the ExtSaveData
+    std::string user_path = game_path + "user/";
+    std::string boss_path = game_path + "boss/";
+    if (!FileUtil::CreateFullPath(user_path))
         return ResultCode(-1); // TODO(Subv): Find the right error code
+    if (!FileUtil::CreateFullPath(boss_path))
+        return ResultCode(-1); // TODO(Subv): Find the right error code
+
+    u8* smdh_icon = Memory::GetPointer(icon_buffer);
+    if (!smdh_icon)
+        return ResultCode(-1); // TODO(Subv): Find the right error code
+
+    // Create the icon
+    FileUtil::IOFile icon_file(game_path + "icon", "wb+");
+    if (!icon_file.IsGood())
+        return ResultCode(-1); // TODO(Subv): Find the right error code
+
+    icon_file.WriteBytes(smdh_icon, icon_size);
     return RESULT_SUCCESS;
 }
 
@@ -441,6 +457,7 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
         return ResultCode(-1); // TODO(Subv): Find the right error code
     }
 
+    // Delete all directories (/user, /boss) and the icon file.
     std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
     std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
     if (!FileUtil::DeleteDirRecursively(extsavedata_path))
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index faab0cb798..357b6b0969 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -177,9 +177,11 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = File
  * @param media_type The media type of the archive to create (NAND / SDMC)
  * @param high The high word of the extdata id to create
  * @param low The low word of the extdata id to create
+ * @param icon_buffer VAddr of the SMDH icon for this ExtSaveData
+ * @param icon_size Size of the SMDH icon
  * @return ResultCode 0 on success or the corresponding code on error
  */
-ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low);
+ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size);
 
 /**
  * Deletes the 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 32db773bb1..0ad44e55e1 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -504,9 +504,9 @@ static void FormatThisUserSaveData(Service::Interface* self) {
  *      6 : Unknown
  *      7 : Unknown
  *      8 : Unknown
- *      9 : Unknown
- *      10: Unknown
- *      11: Unknown
+ *      9 : Size of the SMDH icon
+ *      10: (SMDH Size << 4) | 0x0000000A
+ *      11: Pointer to the SMDH icon for the new ExtSaveData
  *  Outputs:
  *      1 : Result of function, 0 on success, otherwise error code
  */
@@ -516,14 +516,16 @@ static void CreateExtSaveData(Service::Interface* self) {
     MediaType media_type = static_cast<MediaType>(cmd_buff[1] & 0xFF);
     u32 save_low = cmd_buff[2];
     u32 save_high = cmd_buff[3];
+    u32 icon_size = cmd_buff[9];
+    VAddr icon_buffer = cmd_buff[11];
 
     LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
             "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
-            "cmd_buff[9]=%08X cmd_buff[10]=%08X cmd_buff[11]=%08X", save_high, save_low,
-            cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9],
-            cmd_buff[10], cmd_buff[11]);
+            "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low,
+            cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size,
+            cmd_buff[10], icon_buffer);
 
-    cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low).raw;
+    cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size).raw;
 }
 
 /**