fs_user.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/common.h"
  5. #include "common/file_util.h"
  6. #include "common/scope_exit.h"
  7. #include "common/string_util.h"
  8. #include "core/hle/result.h"
  9. #include "core/hle/service/fs/archive.h"
  10. #include "core/hle/service/fs/fs_user.h"
  11. #include "core/settings.h"
  12. ////////////////////////////////////////////////////////////////////////////////////////////////////
  13. // Namespace FS_User
  14. using Kernel::SharedPtr;
  15. using Kernel::Session;
  16. namespace Service {
  17. namespace FS {
  18. static ArchiveHandle MakeArchiveHandle(u32 low_word, u32 high_word) {
  19. return (u64)low_word | ((u64)high_word << 32);
  20. }
  21. static void Initialize(Service::Interface* self) {
  22. u32* cmd_buff = Kernel::GetCommandBuffer();
  23. // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per
  24. // http://3dbrew.org/wiki/FS:Initialize#Request
  25. cmd_buff[1] = RESULT_SUCCESS.raw;
  26. }
  27. /**
  28. * FS_User::OpenFile service function
  29. * Inputs:
  30. * 1 : Transaction
  31. * 2 : Archive handle lower word
  32. * 3 : Archive handle upper word
  33. * 4 : Low path type
  34. * 5 : Low path size
  35. * 6 : Open flags
  36. * 7 : Attributes
  37. * 8 : (LowPathSize << 14) | 2
  38. * 9 : Low path data pointer
  39. * Outputs:
  40. * 1 : Result of function, 0 on success, otherwise error code
  41. * 3 : File handle
  42. */
  43. static void OpenFile(Service::Interface* self) {
  44. u32* cmd_buff = Kernel::GetCommandBuffer();
  45. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  46. auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  47. u32 filename_size = cmd_buff[5];
  48. FileSys::Mode mode; mode.hex = cmd_buff[6];
  49. u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes.
  50. u32 filename_ptr = cmd_buff[9];
  51. FileSys::Path file_path(filename_type, filename_size, filename_ptr);
  52. LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
  53. ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
  54. cmd_buff[1] = file_res.Code().raw;
  55. if (file_res.Succeeded()) {
  56. cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
  57. } else {
  58. cmd_buff[3] = 0;
  59. LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
  60. }
  61. }
  62. /**
  63. * FS_User::OpenFileDirectly service function
  64. * Inputs:
  65. * 1 : Transaction
  66. * 2 : Archive ID
  67. * 3 : Archive low path type
  68. * 4 : Archive low path size
  69. * 5 : File low path type
  70. * 6 : File low path size
  71. * 7 : Flags
  72. * 8 : Attributes
  73. * 9 : (ArchiveLowPathSize << 14) | 0x802
  74. * 10 : Archive low path
  75. * 11 : (FileLowPathSize << 14) | 2
  76. * 12 : File low path
  77. * Outputs:
  78. * 1 : Result of function, 0 on success, otherwise error code
  79. * 3 : File handle
  80. */
  81. static void OpenFileDirectly(Service::Interface* self) {
  82. u32* cmd_buff = Kernel::GetCommandBuffer();
  83. auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]);
  84. auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
  85. u32 archivename_size = cmd_buff[4];
  86. auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]);
  87. u32 filename_size = cmd_buff[6];
  88. FileSys::Mode mode; mode.hex = cmd_buff[7];
  89. u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
  90. u32 archivename_ptr = cmd_buff[10];
  91. u32 filename_ptr = cmd_buff[12];
  92. FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
  93. FileSys::Path file_path(filename_type, filename_size, filename_ptr);
  94. LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d",
  95. archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes);
  96. ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
  97. if (archive_handle.Failed()) {
  98. LOG_ERROR(Service_FS, "failed to get a handle for archive");
  99. cmd_buff[1] = archive_handle.Code().raw;
  100. cmd_buff[3] = 0;
  101. return;
  102. }
  103. SCOPE_EXIT({ CloseArchive(*archive_handle); });
  104. ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode);
  105. cmd_buff[1] = file_res.Code().raw;
  106. if (file_res.Succeeded()) {
  107. cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom();
  108. } else {
  109. cmd_buff[3] = 0;
  110. LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
  111. }
  112. }
  113. /*
  114. * FS_User::DeleteFile service function
  115. * Inputs:
  116. * 2 : Archive handle lower word
  117. * 3 : Archive handle upper word
  118. * 4 : File path string type
  119. * 5 : File path string size
  120. * 7 : File path string data
  121. * Outputs:
  122. * 1 : Result of function, 0 on success, otherwise error code
  123. */
  124. static void DeleteFile(Service::Interface* self) {
  125. u32* cmd_buff = Kernel::GetCommandBuffer();
  126. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  127. auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  128. u32 filename_size = cmd_buff[5];
  129. u32 filename_ptr = cmd_buff[7];
  130. FileSys::Path file_path(filename_type, filename_size, filename_ptr);
  131. LOG_DEBUG(Service_FS, "type=%d size=%d data=%s",
  132. filename_type, filename_size, file_path.DebugStr().c_str());
  133. cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw;
  134. }
  135. /*
  136. * FS_User::RenameFile service function
  137. * Inputs:
  138. * 2 : Source archive handle lower word
  139. * 3 : Source archive handle upper word
  140. * 4 : Source file path type
  141. * 5 : Source file path size
  142. * 6 : Dest archive handle lower word
  143. * 7 : Dest archive handle upper word
  144. * 8 : Dest file path type
  145. * 9 : Dest file path size
  146. * 11: Source file path string data
  147. * 13: Dest file path string
  148. * Outputs:
  149. * 1 : Result of function, 0 on success, otherwise error code
  150. */
  151. static void RenameFile(Service::Interface* self) {
  152. u32* cmd_buff = Kernel::GetCommandBuffer();
  153. ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  154. auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  155. u32 src_filename_size = cmd_buff[5];
  156. ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);;
  157. auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
  158. u32 dest_filename_size = cmd_buff[9];
  159. u32 src_filename_ptr = cmd_buff[11];
  160. u32 dest_filename_ptr = cmd_buff[13];
  161. FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
  162. FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
  163. LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
  164. src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
  165. dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
  166. cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw;
  167. }
  168. /*
  169. * FS_User::DeleteDirectory service function
  170. * Inputs:
  171. * 2 : Archive handle lower word
  172. * 3 : Archive handle upper word
  173. * 4 : Directory path string type
  174. * 5 : Directory path string size
  175. * 7 : Directory path string data
  176. * Outputs:
  177. * 1 : Result of function, 0 on success, otherwise error code
  178. */
  179. static void DeleteDirectory(Service::Interface* self) {
  180. u32* cmd_buff = Kernel::GetCommandBuffer();
  181. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  182. auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  183. u32 dirname_size = cmd_buff[5];
  184. u32 dirname_ptr = cmd_buff[7];
  185. FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
  186. LOG_DEBUG(Service_FS, "type=%d size=%d data=%s",
  187. dirname_type, dirname_size, dir_path.DebugStr().c_str());
  188. cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
  189. }
  190. /*
  191. * FS_User::CreateFile service function
  192. * Inputs:
  193. * 0 : Command header 0x08080202
  194. * 2 : Archive handle lower word
  195. * 3 : Archive handle upper word
  196. * 4 : File path string type
  197. * 5 : File path string size
  198. * 7 : File size (filled with zeroes)
  199. * 10: File path string data
  200. * Outputs:
  201. * 1 : Result of function, 0 on success, otherwise error code
  202. */
  203. static void CreateFile(Service::Interface* self) {
  204. u32* cmd_buff = Kernel::GetCommandBuffer();
  205. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  206. auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  207. u32 filename_size = cmd_buff[5];
  208. u32 file_size = cmd_buff[7];
  209. u32 filename_ptr = cmd_buff[10];
  210. FileSys::Path file_path(filename_type, filename_size, filename_ptr);
  211. LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", filename_type, filename_size, file_path.DebugStr().c_str());
  212. cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw;
  213. }
  214. /*
  215. * FS_User::CreateDirectory service function
  216. * Inputs:
  217. * 2 : Archive handle lower word
  218. * 3 : Archive handle upper word
  219. * 4 : Directory path string type
  220. * 5 : Directory path string size
  221. * 8 : Directory path string data
  222. * Outputs:
  223. * 1 : Result of function, 0 on success, otherwise error code
  224. */
  225. static void CreateDirectory(Service::Interface* self) {
  226. u32* cmd_buff = Kernel::GetCommandBuffer();
  227. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  228. auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  229. u32 dirname_size = cmd_buff[5];
  230. u32 dirname_ptr = cmd_buff[8];
  231. FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
  232. LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
  233. cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw;
  234. }
  235. /*
  236. * FS_User::RenameDirectory service function
  237. * Inputs:
  238. * 2 : Source archive handle lower word
  239. * 3 : Source archive handle upper word
  240. * 4 : Source dir path type
  241. * 5 : Source dir path size
  242. * 6 : Dest archive handle lower word
  243. * 7 : Dest archive handle upper word
  244. * 8 : Dest dir path type
  245. * 9 : Dest dir path size
  246. * 11: Source dir path string data
  247. * 13: Dest dir path string
  248. * Outputs:
  249. * 1 : Result of function, 0 on success, otherwise error code
  250. */
  251. static void RenameDirectory(Service::Interface* self) {
  252. u32* cmd_buff = Kernel::GetCommandBuffer();
  253. ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
  254. auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
  255. u32 src_dirname_size = cmd_buff[5];
  256. ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
  257. auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
  258. u32 dest_dirname_size = cmd_buff[9];
  259. u32 src_dirname_ptr = cmd_buff[11];
  260. u32 dest_dirname_ptr = cmd_buff[13];
  261. FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
  262. FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
  263. LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
  264. src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
  265. dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
  266. cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw;
  267. }
  268. /**
  269. * FS_User::OpenDirectory service function
  270. * Inputs:
  271. * 1 : Archive handle low word
  272. * 2 : Archive handle high word
  273. * 3 : Low path type
  274. * 4 : Low path size
  275. * 7 : (LowPathSize << 14) | 2
  276. * 8 : Low path data pointer
  277. * Outputs:
  278. * 1 : Result of function, 0 on success, otherwise error code
  279. * 3 : Directory handle
  280. */
  281. static void OpenDirectory(Service::Interface* self) {
  282. u32* cmd_buff = Kernel::GetCommandBuffer();
  283. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]);
  284. auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
  285. u32 dirname_size = cmd_buff[4];
  286. u32 dirname_ptr = cmd_buff[6];
  287. FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
  288. LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
  289. ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
  290. cmd_buff[1] = dir_res.Code().raw;
  291. if (dir_res.Succeeded()) {
  292. cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom();
  293. } else {
  294. LOG_ERROR(Service_FS, "failed to get a handle for directory");
  295. }
  296. }
  297. /**
  298. * FS_User::OpenArchive service function
  299. * Inputs:
  300. * 1 : Archive ID
  301. * 2 : Archive low path type
  302. * 3 : Archive low path size
  303. * 4 : (LowPathSize << 14) | 2
  304. * 5 : Archive low path
  305. * Outputs:
  306. * 1 : Result of function, 0 on success, otherwise error code
  307. * 2 : Archive handle lower word (unused)
  308. * 3 : Archive handle upper word (same as file handle)
  309. */
  310. static void OpenArchive(Service::Interface* self) {
  311. u32* cmd_buff = Kernel::GetCommandBuffer();
  312. auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
  313. auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
  314. u32 archivename_size = cmd_buff[3];
  315. u32 archivename_ptr = cmd_buff[5];
  316. FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
  317. LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str());
  318. ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path);
  319. cmd_buff[1] = handle.Code().raw;
  320. if (handle.Succeeded()) {
  321. cmd_buff[2] = *handle & 0xFFFFFFFF;
  322. cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF;
  323. } else {
  324. cmd_buff[2] = cmd_buff[3] = 0;
  325. LOG_ERROR(Service_FS, "failed to get a handle for archive");
  326. }
  327. }
  328. /**
  329. * FS_User::CloseArchive service function
  330. * Inputs:
  331. * 0 : 0x080E0080
  332. * 1 : Archive handle low word
  333. * 2 : Archive handle high word
  334. * Outputs:
  335. * 0 : ??? TODO(yuriks): Verify return header
  336. * 1 : Result of function, 0 on success, otherwise error code
  337. */
  338. static void CloseArchive(Service::Interface* self) {
  339. u32* cmd_buff = Kernel::GetCommandBuffer();
  340. ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]);
  341. cmd_buff[1] = CloseArchive(archive_handle).raw;
  342. }
  343. /*
  344. * FS_User::IsSdmcDetected service function
  345. * Outputs:
  346. * 1 : Result of function, 0 on success, otherwise error code
  347. * 2 : Whether the Sdmc could be detected
  348. */
  349. static void IsSdmcDetected(Service::Interface* self) {
  350. u32* cmd_buff = Kernel::GetCommandBuffer();
  351. cmd_buff[1] = 0;
  352. cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
  353. }
  354. /**
  355. * FS_User::IsSdmcWriteable service function
  356. * Outputs:
  357. * 0 : Command header 0x08180000
  358. * 1 : Result of function, 0 on success, otherwise error code
  359. * 2 : Whether the Sdmc is currently writeable
  360. */
  361. static void IsSdmcWriteable(Service::Interface* self) {
  362. u32* cmd_buff = Kernel::GetCommandBuffer();
  363. cmd_buff[1] = RESULT_SUCCESS.raw;
  364. // If the SD isn't enabled, it can't be writeable...else, stubbed true
  365. cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
  366. LOG_DEBUG(Service_FS, " (STUBBED)");
  367. }
  368. /**
  369. * FS_User::FormatSaveData service function,
  370. * formats the SaveData specified by the input path.
  371. * Inputs:
  372. * 0 : 0x084C0242
  373. * 1 : Archive ID
  374. * 2 : Archive low path type
  375. * 3 : Archive low path size
  376. * 10 : (LowPathSize << 14) | 2
  377. * 11 : Archive low path
  378. * Outputs:
  379. * 1 : Result of function, 0 on success, otherwise error code
  380. */
  381. static void FormatSaveData(Service::Interface* self) {
  382. // TODO(Subv): Find out what the other inputs and outputs of this function are
  383. u32* cmd_buff = Kernel::GetCommandBuffer();
  384. LOG_DEBUG(Service_FS, "(STUBBED)");
  385. auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
  386. auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
  387. u32 archivename_size = cmd_buff[3];
  388. u32 archivename_ptr = cmd_buff[11];
  389. FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
  390. LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str());
  391. if (archive_id != FS::ArchiveIdCode::SaveData) {
  392. // TODO(Subv): What should happen if somebody attempts to format a different archive?
  393. LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", cmd_buff[1]);
  394. cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
  395. return;
  396. }
  397. if (archive_path.GetType() != FileSys::LowPathType::Empty) {
  398. // TODO(Subv): Implement formatting the SaveData of other games
  399. LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported");
  400. cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
  401. return;
  402. }
  403. cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw;
  404. }
  405. /**
  406. * FS_User::FormatThisUserSaveData service function
  407. * Inputs:
  408. * 0: 0x080F0180
  409. * Outputs:
  410. * 1 : Result of function, 0 on success, otherwise error code
  411. */
  412. static void FormatThisUserSaveData(Service::Interface* self) {
  413. u32* cmd_buff = Kernel::GetCommandBuffer();
  414. LOG_DEBUG(Service_FS, "(STUBBED)");
  415. // TODO(Subv): Find out what the inputs and outputs of this function are
  416. cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw;
  417. }
  418. /**
  419. * FS_User::CreateExtSaveData service function
  420. * Inputs:
  421. * 0: 0x08510242
  422. * 1: High word of the saveid to create
  423. * 2: Low word of the saveid to create
  424. * Outputs:
  425. * 1 : Result of function, 0 on success, otherwise error code
  426. */
  427. static void CreateExtSaveData(Service::Interface* self) {
  428. // TODO(Subv): Figure out the other parameters.
  429. u32* cmd_buff = Kernel::GetCommandBuffer();
  430. u32 save_high = cmd_buff[1];
  431. u32 save_low = cmd_buff[2];
  432. // TODO(Subv): For now it is assumed that only SharedExtSaveData can be created like this
  433. cmd_buff[1] = CreateExtSaveData(save_high, save_low).raw;
  434. }
  435. /**
  436. * FS_User::CardSlotIsInserted service function.
  437. * Inputs:
  438. * 0: 0x08210000
  439. * Outputs:
  440. * 1 : Result of function, 0 on success, otherwise error code
  441. * 2 : Whether there is a game card inserted into the slot or not.
  442. */
  443. static void CardSlotIsInserted(Service::Interface* self) {
  444. u32* cmd_buff = Kernel::GetCommandBuffer();
  445. cmd_buff[1] = RESULT_SUCCESS.raw;
  446. cmd_buff[2] = 0;
  447. LOG_WARNING(Service_FS, "(STUBBED) called");
  448. }
  449. const FSUserInterface::FunctionInfo FunctionTable[] = {
  450. {0x000100C6, nullptr, "Dummy1"},
  451. {0x040100C4, nullptr, "Control"},
  452. {0x08010002, Initialize, "Initialize"},
  453. {0x080201C2, OpenFile, "OpenFile"},
  454. {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
  455. {0x08040142, DeleteFile, "DeleteFile"},
  456. {0x08050244, RenameFile, "RenameFile"},
  457. {0x08060142, DeleteDirectory, "DeleteDirectory"},
  458. {0x08070142, nullptr, "DeleteDirectoryRecursively"},
  459. {0x08080202, CreateFile, "CreateFile"},
  460. {0x08090182, CreateDirectory, "CreateDirectory"},
  461. {0x080A0244, RenameDirectory, "RenameDirectory"},
  462. {0x080B0102, OpenDirectory, "OpenDirectory"},
  463. {0x080C00C2, OpenArchive, "OpenArchive"},
  464. {0x080D0144, nullptr, "ControlArchive"},
  465. {0x080E0080, CloseArchive, "CloseArchive"},
  466. {0x080F0180, FormatThisUserSaveData,"FormatThisUserSaveData"},
  467. {0x08100200, nullptr, "CreateSystemSaveData"},
  468. {0x08110040, nullptr, "DeleteSystemSaveData"},
  469. {0x08120080, nullptr, "GetFreeBytes"},
  470. {0x08130000, nullptr, "GetCardType"},
  471. {0x08140000, nullptr, "GetSdmcArchiveResource"},
  472. {0x08150000, nullptr, "GetNandArchiveResource"},
  473. {0x08160000, nullptr, "GetSdmcFatfsErro"},
  474. {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
  475. {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
  476. {0x08190042, nullptr, "GetSdmcCid"},
  477. {0x081A0042, nullptr, "GetNandCid"},
  478. {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
  479. {0x081C0000, nullptr, "GetNandSpeedInfo"},
  480. {0x081D0042, nullptr, "GetSdmcLog"},
  481. {0x081E0042, nullptr, "GetNandLog"},
  482. {0x081F0000, nullptr, "ClearSdmcLog"},
  483. {0x08200000, nullptr, "ClearNandLog"},
  484. {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"},
  485. {0x08220000, nullptr, "CardSlotPowerOn"},
  486. {0x08230000, nullptr, "CardSlotPowerOff"},
  487. {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"},
  488. {0x08250040, nullptr, "CardNorDirectCommand"},
  489. {0x08260080, nullptr, "CardNorDirectCommandWithAddress"},
  490. {0x08270082, nullptr, "CardNorDirectRead"},
  491. {0x082800C2, nullptr, "CardNorDirectReadWithAddress"},
  492. {0x08290082, nullptr, "CardNorDirectWrite"},
  493. {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"},
  494. {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"},
  495. {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"},
  496. {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"},
  497. {0x082E0040, nullptr, "GetProductInfo"},
  498. {0x082F0040, nullptr, "GetProgramLaunchInfo"},
  499. {0x08300182, nullptr, "CreateExtSaveData"},
  500. {0x08310180, nullptr, "CreateSharedExtSaveData"},
  501. {0x08320102, nullptr, "ReadExtSaveDataIcon"},
  502. {0x08330082, nullptr, "EnumerateExtSaveData"},
  503. {0x08340082, nullptr, "EnumerateSharedExtSaveData"},
  504. {0x08350080, nullptr, "DeleteExtSaveData"},
  505. {0x08360080, nullptr, "DeleteSharedExtSaveData"},
  506. {0x08370040, nullptr, "SetCardSpiBaudRate"},
  507. {0x08380040, nullptr, "SetCardSpiBusMode"},
  508. {0x08390000, nullptr, "SendInitializeInfoTo9"},
  509. {0x083A0100, nullptr, "GetSpecialContentIndex"},
  510. {0x083B00C2, nullptr, "GetLegacyRomHeader"},
  511. {0x083C00C2, nullptr, "GetLegacyBannerData"},
  512. {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"},
  513. {0x083E00C2, nullptr, "QueryTotalQuotaSize"},
  514. {0x083F00C0, nullptr, "GetExtDataBlockSize"},
  515. {0x08400040, nullptr, "AbnegateAccessRight"},
  516. {0x08410000, nullptr, "DeleteSdmcRoot"},
  517. {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"},
  518. {0x08430000, nullptr, "InitializeCtrFileSystem"},
  519. {0x08440000, nullptr, "CreateSeed"},
  520. {0x084500C2, nullptr, "GetFormatInfo"},
  521. {0x08460102, nullptr, "GetLegacyRomHeader2"},
  522. {0x08470180, nullptr, "FormatCtrCardUserSaveData"},
  523. {0x08480042, nullptr, "GetSdmcCtrRootPath"},
  524. {0x08490040, nullptr, "GetArchiveResource"},
  525. {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
  526. {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
  527. {0x084C0242, FormatSaveData, "FormatSaveData"},
  528. {0x084D0102, nullptr, "GetLegacySubBannerData"},
  529. {0x084E0342, nullptr, "UpdateSha256Context"},
  530. {0x084F0102, nullptr, "ReadSpecialFile"},
  531. {0x08500040, nullptr, "GetSpecialFileSize"},
  532. {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
  533. {0x08520100, nullptr, "DeleteExtSaveData"},
  534. {0x08580000, nullptr, "GetMovableSedHashedKeyYRandomData"},
  535. {0x08610042, nullptr, "InitializeWithSdkVersion"},
  536. {0x08620040, nullptr, "SetPriority"},
  537. {0x08630000, nullptr, "GetPriority"},
  538. };
  539. ////////////////////////////////////////////////////////////////////////////////////////////////////
  540. // Interface class
  541. FSUserInterface::FSUserInterface() {
  542. Register(FunctionTable);
  543. }
  544. } // namespace FS
  545. } // namespace Service