program_metadata.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cinttypes>
  5. #include "common/file_util.h"
  6. #include "common/logging/log.h"
  7. #include "core/file_sys/program_metadata.h"
  8. #include "core/loader/loader.h"
  9. namespace FileSys {
  10. Loader::ResultStatus ProgramMetadata::Load(const std::string& file_path) {
  11. FileUtil::IOFile file(file_path, "rb");
  12. if (!file.IsOpen())
  13. return Loader::ResultStatus::Error;
  14. std::vector<u8> file_data(file.GetSize());
  15. if (!file.ReadBytes(file_data.data(), file_data.size()))
  16. return Loader::ResultStatus::Error;
  17. Loader::ResultStatus result = Load(file_data);
  18. if (result != Loader::ResultStatus::Success)
  19. LOG_ERROR(Service_FS, "Failed to load NPDM from file %s!", file_path.c_str());
  20. return result;
  21. }
  22. Loader::ResultStatus ProgramMetadata::Load(const std::vector<u8> file_data, size_t offset) {
  23. size_t total_size = static_cast<size_t>(file_data.size() - offset);
  24. if (total_size < sizeof(Header))
  25. return Loader::ResultStatus::Error;
  26. size_t header_offset = offset;
  27. memcpy(&npdm_header, &file_data[offset], sizeof(Header));
  28. size_t aci_offset = header_offset + npdm_header.aci_offset;
  29. size_t acid_offset = header_offset + npdm_header.acid_offset;
  30. memcpy(&aci_header, &file_data[aci_offset], sizeof(AciHeader));
  31. memcpy(&acid_header, &file_data[acid_offset], sizeof(AcidHeader));
  32. size_t fac_offset = acid_offset + acid_header.fac_offset;
  33. size_t fah_offset = aci_offset + aci_header.fah_offset;
  34. memcpy(&acid_file_access, &file_data[fac_offset], sizeof(FileAccessControl));
  35. memcpy(&aci_file_access, &file_data[fah_offset], sizeof(FileAccessHeader));
  36. return Loader::ResultStatus::Success;
  37. }
  38. bool ProgramMetadata::Is64BitProgram() const {
  39. return npdm_header.has_64_bit_instructions;
  40. }
  41. ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const {
  42. return npdm_header.address_space_type;
  43. }
  44. u8 ProgramMetadata::GetMainThreadPriority() const {
  45. return npdm_header.main_thread_priority;
  46. }
  47. u8 ProgramMetadata::GetMainThreadCore() const {
  48. return npdm_header.main_thread_cpu;
  49. }
  50. u32 ProgramMetadata::GetMainThreadStackSize() const {
  51. return npdm_header.main_stack_size;
  52. }
  53. u64 ProgramMetadata::GetTitleID() const {
  54. return aci_header.title_id;
  55. }
  56. u64 ProgramMetadata::GetFilesystemPermissions() const {
  57. return aci_file_access.permissions;
  58. }
  59. void ProgramMetadata::Print() const {
  60. LOG_DEBUG(Service_FS, "Magic: %.4s", npdm_header.magic.data());
  61. LOG_DEBUG(Service_FS, "Main thread priority: 0x%02x", npdm_header.main_thread_priority);
  62. LOG_DEBUG(Service_FS, "Main thread core: %u", npdm_header.main_thread_cpu);
  63. LOG_DEBUG(Service_FS, "Main thread stack size: 0x%x bytes", npdm_header.main_stack_size);
  64. LOG_DEBUG(Service_FS, "Process category: %u", npdm_header.process_category);
  65. LOG_DEBUG(Service_FS, "Flags: %02x", npdm_header.flags);
  66. LOG_DEBUG(Service_FS, " > 64-bit instructions: %s",
  67. npdm_header.has_64_bit_instructions ? "YES" : "NO");
  68. auto address_space = "Unknown";
  69. switch (npdm_header.address_space_type) {
  70. case ProgramAddressSpaceType::Is64Bit:
  71. address_space = "64-bit";
  72. break;
  73. case ProgramAddressSpaceType::Is32Bit:
  74. address_space = "32-bit";
  75. break;
  76. }
  77. LOG_DEBUG(Service_FS, " > Address space: %s\n", address_space);
  78. // Begin ACID printing (potential perms, signed)
  79. LOG_DEBUG(Service_FS, "Magic: %.4s", acid_header.magic.data());
  80. LOG_DEBUG(Service_FS, "Flags: %02x", acid_header.flags);
  81. LOG_DEBUG(Service_FS, " > Is Retail: %s", acid_header.is_retail ? "YES" : "NO");
  82. LOG_DEBUG(Service_FS, "Title ID Min: %016" PRIX64, acid_header.title_id_min);
  83. LOG_DEBUG(Service_FS, "Title ID Max: %016" PRIX64, acid_header.title_id_max);
  84. LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", acid_file_access.permissions);
  85. // Begin ACI0 printing (actual perms, unsigned)
  86. LOG_DEBUG(Service_FS, "Magic: %.4s", aci_header.magic.data());
  87. LOG_DEBUG(Service_FS, "Title ID: %016" PRIX64, aci_header.title_id);
  88. LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", aci_file_access.permissions);
  89. }
  90. } // namespace FileSys