archive.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2
  3. // Refer to the license.txt file included.
  4. #include "common/common_types.h"
  5. #include "common/math_util.h"
  6. #include "core/file_sys/archive.h"
  7. #include "core/hle/service/service.h"
  8. #include "core/hle/kernel/archive.h"
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////
  10. // Kernel namespace
  11. namespace Kernel {
  12. // Command to access archive file
  13. enum class FileCommand : u32 {
  14. Dummy1 = 0x000100C6,
  15. Control = 0x040100C4,
  16. OpenSubFile = 0x08010100,
  17. Read = 0x080200C2,
  18. Write = 0x08030102,
  19. GetSize = 0x08040000,
  20. SetSize = 0x08050080,
  21. GetAttributes = 0x08060000,
  22. SetAttributes = 0x08070040,
  23. Close = 0x08080000,
  24. Flush = 0x08090000,
  25. };
  26. class Archive : public Object {
  27. public:
  28. std::string GetTypeName() const { return "Archive"; }
  29. std::string GetName() const { return name; }
  30. static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; }
  31. Kernel::HandleType GetHandleType() const { return HandleType::Archive; }
  32. std::string name; ///< Name of archive (optional)
  33. FileSys::Archive* backend; ///< Archive backend interface
  34. /**
  35. * Synchronize kernel object
  36. * @param wait Boolean wait set if current thread should wait as a result of sync operation
  37. * @return Result of operation, 0 on success, otherwise error code
  38. */
  39. Result SyncRequest(bool* wait) {
  40. u32* cmd_buff = Service::GetCommandBuffer();
  41. FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
  42. switch (cmd) {
  43. // Read from archive...
  44. case FileCommand::Read:
  45. {
  46. u64 offset = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
  47. u32 length = cmd_buff[3];
  48. u32 address = cmd_buff[5];
  49. // Number of bytes read
  50. cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address));
  51. break;
  52. }
  53. // Write to archive...
  54. case FileCommand::Write:
  55. {
  56. u64 offset = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
  57. u32 length = cmd_buff[3];
  58. u32 flush = cmd_buff[4];
  59. u32 address = cmd_buff[6];
  60. // Number of bytes written
  61. cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address));
  62. break;
  63. }
  64. case FileCommand::GetSize:
  65. {
  66. u64 filesize = (u64) backend->GetSize();
  67. cmd_buff[2] = (u32) filesize; // Lower word
  68. cmd_buff[3] = (u32) (filesize >> 32); // Upper word
  69. break;
  70. }
  71. case FileCommand::SetSize:
  72. {
  73. backend->SetSize(cmd_buff[1] | ((u64)cmd_buff[2] << 32));
  74. break;
  75. }
  76. // Unknown command...
  77. default:
  78. {
  79. ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
  80. return -1;
  81. }
  82. }
  83. cmd_buff[1] = 0; // No error
  84. return 0;
  85. }
  86. /**
  87. * Wait for kernel object to synchronize
  88. * @param wait Boolean wait set if current thread should wait as a result of sync operation
  89. * @return Result of operation, 0 on success, otherwise error code
  90. */
  91. Result WaitSynchronization(bool* wait) {
  92. // TODO(bunnei): ImplementMe
  93. ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
  94. return 0;
  95. }
  96. };
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////
  98. std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
  99. /**
  100. * Opens an archive
  101. * @param id_code IdCode of the archive to open
  102. * @return Handle to archive if it exists, otherwise a null handle (0)
  103. */
  104. Handle OpenArchive(FileSys::Archive::IdCode id_code) {
  105. auto itr = g_archive_map.find(id_code);
  106. if (itr == g_archive_map.end()) {
  107. return 0;
  108. }
  109. return itr->second;
  110. }
  111. /**
  112. * Mounts an archive
  113. * @param archive Pointer to the archive to mount
  114. * @return Result of operation, 0 on success, otherwise error code
  115. */
  116. Result MountArchive(Archive* archive) {
  117. FileSys::Archive::IdCode id_code = archive->backend->GetIdCode();
  118. if (0 != OpenArchive(id_code)) {
  119. ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code);
  120. return -1;
  121. }
  122. g_archive_map[id_code] = archive->GetHandle();
  123. INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str());
  124. return 0;
  125. }
  126. /**
  127. * Creates an Archive
  128. * @param handle Handle to newly created archive object
  129. * @param backend File system backend interface to the archive
  130. * @param name Optional name of Archive
  131. * @return Newly created Archive object
  132. */
  133. Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) {
  134. Archive* archive = new Archive;
  135. handle = Kernel::g_object_pool.Create(archive);
  136. archive->name = name;
  137. archive->backend = backend;
  138. MountArchive(archive);
  139. return archive;
  140. }
  141. /**
  142. * Creates an Archive
  143. * @param backend File system backend interface to the archive
  144. * @param name Optional name of Archive
  145. * @return Handle to newly created Archive object
  146. */
  147. Handle CreateArchive(FileSys::Archive* backend, const std::string& name) {
  148. Handle handle;
  149. CreateArchive(handle, backend, name);
  150. return handle;
  151. }
  152. /// Initialize archives
  153. void ArchiveInit() {
  154. g_archive_map.clear();
  155. }
  156. /// Shutdown archives
  157. void ArchiveShutdown() {
  158. g_archive_map.clear();
  159. }
  160. } // namespace Kernel