summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2016-08-27 01:04:26 -0700
committerGravatar Yuri Kunde Schlesner2016-08-27 01:04:26 -0700
commit1f7ec4be9bf86f26d57555f7fd6b43851557e47d (patch)
treeccd129bf4b6b8baef6d8779bc2d21eb14d212619 /src
parentMerge pull request #2022 from MerryMage/issue-tpl (diff)
downloadyuzu-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.cpp7
-rw-r--r--src/core/hle/service/apt/bcfnt/bcfnt.cpp79
-rw-r--r--src/core/hle/service/apt/bcfnt/bcfnt.h12
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 {
9namespace APT { 9namespace APT {
10namespace BCFNT { 10namespace BCFNT {
11 11
12void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr previous_address, VAddr new_address) { 12void 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(&section_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(&section_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
25struct SectionHeader {
26 u8 magic[4];
27 u32_le section_size;
28};
29
25struct FINF { 30struct 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 */
83void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr previous_address, VAddr new_address); 89void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address);
84 90
85} // namespace BCFNT 91} // namespace BCFNT
86} // namespace APT 92} // namespace APT