pl_u.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/common_paths.h"
  5. #include "common/file_util.h"
  6. #include "core/core.h"
  7. #include "core/hle/ipc_helpers.h"
  8. #include "core/hle/service/ns/pl_u.h"
  9. namespace Service::NS {
  10. struct FontRegion {
  11. u32 offset;
  12. u32 size;
  13. };
  14. // The below data is specific to shared font data dumped from Switch on f/w 2.2
  15. // Virtual address and offsets/sizes likely will vary by dump
  16. static constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL};
  17. static constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000};
  18. static constexpr std::array<FontRegion, 6> SHARED_FONT_REGIONS{
  19. FontRegion{0x00000008, 0x001fe764}, FontRegion{0x001fe774, 0x00773e58},
  20. FontRegion{0x009725d4, 0x0001aca8}, FontRegion{0x0098d284, 0x00369cec},
  21. FontRegion{0x00cf6f78, 0x0039b858}, FontRegion{0x010927d8, 0x00019e80},
  22. };
  23. enum class LoadState : u32 {
  24. Loading = 0,
  25. Done = 1,
  26. };
  27. PL_U::PL_U() : ServiceFramework("pl:u") {
  28. static const FunctionInfo functions[] = {
  29. {0, &PL_U::RequestLoad, "RequestLoad"},
  30. {1, &PL_U::GetLoadState, "GetLoadState"},
  31. {2, &PL_U::GetSize, "GetSize"},
  32. {3, &PL_U::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
  33. {4, &PL_U::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
  34. {5, &PL_U::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
  35. };
  36. RegisterHandlers(functions);
  37. // Attempt to load shared font data from disk
  38. const std::string filepath{FileUtil::GetUserPath(D_SYSDATA_IDX) + SHARED_FONT};
  39. FileUtil::CreateFullPath(filepath); // Create path if not already created
  40. FileUtil::IOFile file(filepath, "rb");
  41. shared_font = std::make_shared<std::vector<u8>>(SHARED_FONT_MEM_SIZE);
  42. if (file.IsOpen()) {
  43. // Read shared font data
  44. ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE);
  45. file.ReadBytes(shared_font->data(), shared_font->size());
  46. } else {
  47. LOG_WARNING(Service_NS, "Unable to load shared font: {}", filepath);
  48. }
  49. }
  50. void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
  51. IPC::RequestParser rp{ctx};
  52. const u32 shared_font_type{rp.Pop<u32>()};
  53. LOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
  54. IPC::ResponseBuilder rb{ctx, 2};
  55. rb.Push(RESULT_SUCCESS);
  56. }
  57. void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
  58. IPC::RequestParser rp{ctx};
  59. const u32 font_id{rp.Pop<u32>()};
  60. LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
  61. IPC::ResponseBuilder rb{ctx, 3};
  62. rb.Push(RESULT_SUCCESS);
  63. rb.Push<u32>(static_cast<u32>(LoadState::Done));
  64. }
  65. void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
  66. IPC::RequestParser rp{ctx};
  67. const u32 font_id{rp.Pop<u32>()};
  68. LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
  69. IPC::ResponseBuilder rb{ctx, 3};
  70. rb.Push(RESULT_SUCCESS);
  71. rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size);
  72. }
  73. void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
  74. IPC::RequestParser rp{ctx};
  75. const u32 font_id{rp.Pop<u32>()};
  76. LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
  77. IPC::ResponseBuilder rb{ctx, 3};
  78. rb.Push(RESULT_SUCCESS);
  79. rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset);
  80. }
  81. void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
  82. // TODO(bunnei): This is a less-than-ideal solution to load a RAM dump of the Switch shared
  83. // font data. This (likely) relies on exact address, size, and offsets from the original
  84. // dump. In the future, we need to replace this with a more robust solution.
  85. // Map backing memory for the font data
  86. Core::CurrentProcess()->vm_manager.MapMemoryBlock(
  87. SHARED_FONT_MEM_VADDR, shared_font, 0, SHARED_FONT_MEM_SIZE, Kernel::MemoryState::Shared);
  88. // Create shared font memory object
  89. shared_font_mem = Kernel::SharedMemory::Create(
  90. Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
  91. Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
  92. "PL_U:shared_font_mem");
  93. LOG_DEBUG(Service_NS, "called");
  94. IPC::ResponseBuilder rb{ctx, 2, 1};
  95. rb.Push(RESULT_SUCCESS);
  96. rb.PushCopyObjects(shared_font_mem);
  97. }
  98. void PL_U::GetSharedFontInOrderOfPriority(Kernel::HLERequestContext& ctx) {
  99. IPC::RequestParser rp{ctx};
  100. const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
  101. LOG_DEBUG(Service_NS, "called, language_code=%lx", language_code);
  102. IPC::ResponseBuilder rb{ctx, 4};
  103. std::vector<u32> font_codes;
  104. std::vector<u32> font_offsets;
  105. std::vector<u32> font_sizes;
  106. // TODO(ogniK): Have actual priority order
  107. for (size_t i = 0; i < SHARED_FONT_REGIONS.size(); i++) {
  108. font_codes.push_back(static_cast<u32>(i));
  109. font_offsets.push_back(SHARED_FONT_REGIONS[i].offset);
  110. font_sizes.push_back(SHARED_FONT_REGIONS[i].size);
  111. }
  112. ctx.WriteBuffer(font_codes.data(), font_codes.size(), 0);
  113. ctx.WriteBuffer(font_offsets.data(), font_offsets.size(), 1);
  114. ctx.WriteBuffer(font_sizes.data(), font_sizes.size(), 2);
  115. rb.Push(RESULT_SUCCESS);
  116. rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded
  117. rb.Push<u32>(static_cast<u32>(font_codes.size()));
  118. }
  119. } // namespace Service::NS