program_metadata.cpp 4.3 KB

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