diff options
| author | 2016-08-27 01:04:26 -0700 | |
|---|---|---|
| committer | 2016-08-27 01:04:26 -0700 | |
| commit | 1f7ec4be9bf86f26d57555f7fd6b43851557e47d (patch) | |
| tree | ccd129bf4b6b8baef6d8779bc2d21eb14d212619 /src | |
| parent | Merge pull request #2022 from MerryMage/issue-tpl (diff) | |
| download | yuzu-1f7ec4be9bf86f26d57555f7fd6b43851557e47d.tar.gz yuzu-1f7ec4be9bf86f26d57555f7fd6b43851557e47d.tar.xz yuzu-1f7ec4be9bf86f26d57555f7fd6b43851557e47d.zip | |
Auto-detect original shared_font.bin memory base
This allows a file dumped from either an o3DS or a n3DS (and potentially
even an original unrebased file) to be used.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/service/apt/bcfnt/bcfnt.cpp | 79 | ||||
| -rw-r--r-- | src/core/hle/service/apt/bcfnt/bcfnt.h | 12 |
3 files changed, 68 insertions, 30 deletions
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index c009e6c98..4f4ee75cd 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp | |||
| @@ -81,13 +81,8 @@ void GetSharedFont(Service::Interface* self) { | |||
| 81 | 81 | ||
| 82 | // The shared font has to be relocated to the new address before being passed to the application. | 82 | // The shared font has to be relocated to the new address before being passed to the application. |
| 83 | VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); | 83 | VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); |
| 84 | // The shared font dumped by 3dsutils (https://github.com/citra-emu/3dsutils) uses this address as base, | ||
| 85 | // so we relocate it from there to our real address. | ||
| 86 | // TODO(Subv): This address is wrong if the shared font is dumped from a n3DS, | ||
| 87 | // we need a way to automatically calculate the original address of the font from the file. | ||
| 88 | static const VAddr SHARED_FONT_VADDR = 0x18000000; | ||
| 89 | if (!shared_font_relocated) { | 84 | if (!shared_font_relocated) { |
| 90 | BCFNT::RelocateSharedFont(shared_font_mem, SHARED_FONT_VADDR, target_address); | 85 | BCFNT::RelocateSharedFont(shared_font_mem, target_address); |
| 91 | shared_font_relocated = true; | 86 | shared_font_relocated = true; |
| 92 | } | 87 | } |
| 93 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); | 88 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); |
diff --git a/src/core/hle/service/apt/bcfnt/bcfnt.cpp b/src/core/hle/service/apt/bcfnt/bcfnt.cpp index b0d39d4a5..57eb39d75 100644 --- a/src/core/hle/service/apt/bcfnt/bcfnt.cpp +++ b/src/core/hle/service/apt/bcfnt/bcfnt.cpp | |||
| @@ -9,60 +9,97 @@ namespace Service { | |||
| 9 | namespace APT { | 9 | namespace APT { |
| 10 | namespace BCFNT { | 10 | namespace BCFNT { |
| 11 | 11 | ||
| 12 | void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr previous_address, VAddr new_address) { | 12 | void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address) { |
| 13 | static const u32 SharedFontStartOffset = 0x80; | 13 | static const u32 SharedFontStartOffset = 0x80; |
| 14 | u8* data = shared_font->GetPointer(SharedFontStartOffset); | 14 | const u8* cfnt_ptr = shared_font->GetPointer(SharedFontStartOffset); |
| 15 | 15 | ||
| 16 | CFNT cfnt; | 16 | CFNT cfnt; |
| 17 | memcpy(&cfnt, data, sizeof(cfnt)); | 17 | memcpy(&cfnt, cfnt_ptr, sizeof(cfnt)); |
| 18 | 18 | ||
| 19 | // Advance past the header | 19 | u32 assumed_cmap_offset = 0; |
| 20 | data = shared_font->GetPointer(SharedFontStartOffset + cfnt.header_size); | 20 | u32 assumed_cwdh_offset = 0; |
| 21 | u32 assumed_tglp_offset = 0; | ||
| 22 | u32 first_cmap_offset = 0; | ||
| 23 | u32 first_cwdh_offset = 0; | ||
| 24 | u32 first_tglp_offset = 0; | ||
| 21 | 25 | ||
| 26 | // First discover the location of sections so that the rebase offset can be auto-detected | ||
| 27 | u32 current_offset = SharedFontStartOffset + cfnt.header_size; | ||
| 22 | for (unsigned block = 0; block < cfnt.num_blocks; ++block) { | 28 | for (unsigned block = 0; block < cfnt.num_blocks; ++block) { |
| 29 | const u8* data = shared_font->GetPointer(current_offset); | ||
| 30 | |||
| 31 | SectionHeader section_header; | ||
| 32 | memcpy(§ion_header, data, sizeof(section_header)); | ||
| 33 | |||
| 34 | if (first_cmap_offset == 0 && memcmp(section_header.magic, "CMAP", 4) == 0) { | ||
| 35 | first_cmap_offset = current_offset; | ||
| 36 | } else if (first_cwdh_offset == 0 && memcmp(section_header.magic, "CWDH", 4) == 0) { | ||
| 37 | first_cwdh_offset = current_offset; | ||
| 38 | } else if (first_tglp_offset == 0 && memcmp(section_header.magic, "TGLP", 4) == 0) { | ||
| 39 | first_tglp_offset = current_offset; | ||
| 40 | } else if (memcmp(section_header.magic, "FINF", 4) == 0) { | ||
| 41 | BCFNT::FINF finf; | ||
| 42 | memcpy(&finf, data, sizeof(finf)); | ||
| 43 | |||
| 44 | assumed_cmap_offset = finf.cmap_offset - sizeof(SectionHeader); | ||
| 45 | assumed_cwdh_offset = finf.cwdh_offset - sizeof(SectionHeader); | ||
| 46 | assumed_tglp_offset = finf.tglp_offset - sizeof(SectionHeader); | ||
| 47 | } | ||
| 48 | |||
| 49 | current_offset += section_header.section_size; | ||
| 50 | } | ||
| 51 | |||
| 52 | u32 previous_base = assumed_cmap_offset - first_cmap_offset; | ||
| 53 | ASSERT(previous_base == assumed_cwdh_offset - first_cwdh_offset); | ||
| 54 | ASSERT(previous_base == assumed_tglp_offset - first_tglp_offset); | ||
| 55 | |||
| 56 | u32 offset = new_address - previous_base; | ||
| 57 | |||
| 58 | // Reset pointer back to start of sections and do the actual rebase | ||
| 59 | current_offset = SharedFontStartOffset + cfnt.header_size; | ||
| 60 | for (unsigned block = 0; block < cfnt.num_blocks; ++block) { | ||
| 61 | u8* data = shared_font->GetPointer(current_offset); | ||
| 62 | |||
| 63 | SectionHeader section_header; | ||
| 64 | memcpy(§ion_header, data, sizeof(section_header)); | ||
| 23 | 65 | ||
| 24 | u32 section_size = 0; | 66 | if (memcmp(section_header.magic, "FINF", 4) == 0) { |
| 25 | if (memcmp(data, "FINF", 4) == 0) { | ||
| 26 | BCFNT::FINF finf; | 67 | BCFNT::FINF finf; |
| 27 | memcpy(&finf, data, sizeof(finf)); | 68 | memcpy(&finf, data, sizeof(finf)); |
| 28 | section_size = finf.section_size; | ||
| 29 | 69 | ||
| 30 | // Relocate the offsets in the FINF section | 70 | // Relocate the offsets in the FINF section |
| 31 | finf.cmap_offset += new_address - previous_address; | 71 | finf.cmap_offset += offset; |
| 32 | finf.cwdh_offset += new_address - previous_address; | 72 | finf.cwdh_offset += offset; |
| 33 | finf.tglp_offset += new_address - previous_address; | 73 | finf.tglp_offset += offset; |
| 34 | 74 | ||
| 35 | memcpy(data, &finf, sizeof(finf)); | 75 | memcpy(data, &finf, sizeof(finf)); |
| 36 | } else if (memcmp(data, "CMAP", 4) == 0) { | 76 | } else if (memcmp(section_header.magic, "CMAP", 4) == 0) { |
| 37 | BCFNT::CMAP cmap; | 77 | BCFNT::CMAP cmap; |
| 38 | memcpy(&cmap, data, sizeof(cmap)); | 78 | memcpy(&cmap, data, sizeof(cmap)); |
| 39 | section_size = cmap.section_size; | ||
| 40 | 79 | ||
| 41 | // Relocate the offsets in the CMAP section | 80 | // Relocate the offsets in the CMAP section |
| 42 | cmap.next_cmap_offset += new_address - previous_address; | 81 | cmap.next_cmap_offset += offset; |
| 43 | 82 | ||
| 44 | memcpy(data, &cmap, sizeof(cmap)); | 83 | memcpy(data, &cmap, sizeof(cmap)); |
| 45 | } else if (memcmp(data, "CWDH", 4) == 0) { | 84 | } else if (memcmp(section_header.magic, "CWDH", 4) == 0) { |
| 46 | BCFNT::CWDH cwdh; | 85 | BCFNT::CWDH cwdh; |
| 47 | memcpy(&cwdh, data, sizeof(cwdh)); | 86 | memcpy(&cwdh, data, sizeof(cwdh)); |
| 48 | section_size = cwdh.section_size; | ||
| 49 | 87 | ||
| 50 | // Relocate the offsets in the CWDH section | 88 | // Relocate the offsets in the CWDH section |
| 51 | cwdh.next_cwdh_offset += new_address - previous_address; | 89 | cwdh.next_cwdh_offset += offset; |
| 52 | 90 | ||
| 53 | memcpy(data, &cwdh, sizeof(cwdh)); | 91 | memcpy(data, &cwdh, sizeof(cwdh)); |
| 54 | } else if (memcmp(data, "TGLP", 4) == 0) { | 92 | } else if (memcmp(section_header.magic, "TGLP", 4) == 0) { |
| 55 | BCFNT::TGLP tglp; | 93 | BCFNT::TGLP tglp; |
| 56 | memcpy(&tglp, data, sizeof(tglp)); | 94 | memcpy(&tglp, data, sizeof(tglp)); |
| 57 | section_size = tglp.section_size; | ||
| 58 | 95 | ||
| 59 | // Relocate the offsets in the TGLP section | 96 | // Relocate the offsets in the TGLP section |
| 60 | tglp.sheet_data_offset += new_address - previous_address; | 97 | tglp.sheet_data_offset += offset; |
| 61 | 98 | ||
| 62 | memcpy(data, &tglp, sizeof(tglp)); | 99 | memcpy(data, &tglp, sizeof(tglp)); |
| 63 | } | 100 | } |
| 64 | 101 | ||
| 65 | data += section_size; | 102 | current_offset += section_header.section_size; |
| 66 | } | 103 | } |
| 67 | } | 104 | } |
| 68 | 105 | ||
diff --git a/src/core/hle/service/apt/bcfnt/bcfnt.h b/src/core/hle/service/apt/bcfnt/bcfnt.h index 388c6bea0..8936dcf63 100644 --- a/src/core/hle/service/apt/bcfnt/bcfnt.h +++ b/src/core/hle/service/apt/bcfnt/bcfnt.h | |||
| @@ -22,6 +22,11 @@ struct CFNT { | |||
| 22 | u32_le num_blocks; | 22 | u32_le num_blocks; |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | struct SectionHeader { | ||
| 26 | u8 magic[4]; | ||
| 27 | u32_le section_size; | ||
| 28 | }; | ||
| 29 | |||
| 25 | struct FINF { | 30 | struct FINF { |
| 26 | u8 magic[4]; | 31 | u8 magic[4]; |
| 27 | u32_le section_size; | 32 | u32_le section_size; |
| @@ -75,12 +80,13 @@ struct CWDH { | |||
| 75 | }; | 80 | }; |
| 76 | 81 | ||
| 77 | /** | 82 | /** |
| 78 | * Relocates the internal addresses of the BCFNT Shared Font to the new base. | 83 | * Relocates the internal addresses of the BCFNT Shared Font to the new base. The current base will |
| 84 | * be auto-detected based on the file headers. | ||
| 85 | * | ||
| 79 | * @param shared_font SharedMemory object that contains the Shared Font | 86 | * @param shared_font SharedMemory object that contains the Shared Font |
| 80 | * @param previous_address Previous address at which the offsets in the structure were based. | ||
| 81 | * @param new_address New base for the offsets in the structure. | 87 | * @param new_address New base for the offsets in the structure. |
| 82 | */ | 88 | */ |
| 83 | void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr previous_address, VAddr new_address); | 89 | void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address); |
| 84 | 90 | ||
| 85 | } // namespace BCFNT | 91 | } // namespace BCFNT |
| 86 | } // namespace APT | 92 | } // namespace APT |