fs_user.cpp 29 KB

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