mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #2023 from yuriks/autobase-bcfnt
Auto-detect original shared_font.bin memory base
This commit is contained in:
		
						commit
						7c934c5164
					
				@ -81,13 +81,8 @@ void GetSharedFont(Service::Interface* self) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // The shared font has to be relocated to the new address before being passed to the application.
 | 
					    // The shared font has to be relocated to the new address before being passed to the application.
 | 
				
			||||||
    VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
 | 
					    VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
 | 
				
			||||||
    // The shared font dumped by 3dsutils (https://github.com/citra-emu/3dsutils) uses this address as base,
 | 
					 | 
				
			||||||
    // so we relocate it from there to our real address.
 | 
					 | 
				
			||||||
    // TODO(Subv): This address is wrong if the shared font is dumped from a n3DS,
 | 
					 | 
				
			||||||
    // we need a way to automatically calculate the original address of the font from the file.
 | 
					 | 
				
			||||||
    static const VAddr SHARED_FONT_VADDR = 0x18000000;
 | 
					 | 
				
			||||||
    if (!shared_font_relocated) {
 | 
					    if (!shared_font_relocated) {
 | 
				
			||||||
        BCFNT::RelocateSharedFont(shared_font_mem, SHARED_FONT_VADDR, target_address);
 | 
					        BCFNT::RelocateSharedFont(shared_font_mem, target_address);
 | 
				
			||||||
        shared_font_relocated = true;
 | 
					        shared_font_relocated = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
 | 
					    cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
 | 
				
			||||||
 | 
				
			|||||||
@ -9,60 +9,97 @@ namespace Service {
 | 
				
			|||||||
namespace APT {
 | 
					namespace APT {
 | 
				
			||||||
namespace BCFNT {
 | 
					namespace BCFNT {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr previous_address, VAddr new_address) {
 | 
					void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address) {
 | 
				
			||||||
    static const u32 SharedFontStartOffset = 0x80;
 | 
					    static const u32 SharedFontStartOffset = 0x80;
 | 
				
			||||||
    u8* data = shared_font->GetPointer(SharedFontStartOffset);
 | 
					    const u8* cfnt_ptr = shared_font->GetPointer(SharedFontStartOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CFNT cfnt;
 | 
					    CFNT cfnt;
 | 
				
			||||||
    memcpy(&cfnt, data, sizeof(cfnt));
 | 
					    memcpy(&cfnt, cfnt_ptr, sizeof(cfnt));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Advance past the header
 | 
					    u32 assumed_cmap_offset = 0;
 | 
				
			||||||
    data = shared_font->GetPointer(SharedFontStartOffset + cfnt.header_size);
 | 
					    u32 assumed_cwdh_offset = 0;
 | 
				
			||||||
 | 
					    u32 assumed_tglp_offset = 0;
 | 
				
			||||||
 | 
					    u32 first_cmap_offset = 0;
 | 
				
			||||||
 | 
					    u32 first_cwdh_offset = 0;
 | 
				
			||||||
 | 
					    u32 first_tglp_offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // First discover the location of sections so that the rebase offset can be auto-detected
 | 
				
			||||||
 | 
					    u32 current_offset = SharedFontStartOffset + cfnt.header_size;
 | 
				
			||||||
    for (unsigned block = 0; block < cfnt.num_blocks; ++block) {
 | 
					    for (unsigned block = 0; block < cfnt.num_blocks; ++block) {
 | 
				
			||||||
 | 
					        const u8* data = shared_font->GetPointer(current_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        u32 section_size = 0;
 | 
					        SectionHeader section_header;
 | 
				
			||||||
        if (memcmp(data, "FINF", 4) == 0) {
 | 
					        memcpy(§ion_header, data, sizeof(section_header));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (first_cmap_offset == 0 && memcmp(section_header.magic, "CMAP", 4) == 0) {
 | 
				
			||||||
 | 
					            first_cmap_offset = current_offset;
 | 
				
			||||||
 | 
					        } else if (first_cwdh_offset == 0 && memcmp(section_header.magic, "CWDH", 4) == 0) {
 | 
				
			||||||
 | 
					            first_cwdh_offset = current_offset;
 | 
				
			||||||
 | 
					        } else if (first_tglp_offset == 0 && memcmp(section_header.magic, "TGLP", 4) == 0) {
 | 
				
			||||||
 | 
					            first_tglp_offset = current_offset;
 | 
				
			||||||
 | 
					        } else if (memcmp(section_header.magic, "FINF", 4) == 0) {
 | 
				
			||||||
 | 
					            BCFNT::FINF finf;
 | 
				
			||||||
 | 
					            memcpy(&finf, data, sizeof(finf));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            assumed_cmap_offset = finf.cmap_offset - sizeof(SectionHeader);
 | 
				
			||||||
 | 
					            assumed_cwdh_offset = finf.cwdh_offset - sizeof(SectionHeader);
 | 
				
			||||||
 | 
					            assumed_tglp_offset = finf.tglp_offset - sizeof(SectionHeader);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        current_offset += section_header.section_size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u32 previous_base = assumed_cmap_offset - first_cmap_offset;
 | 
				
			||||||
 | 
					    ASSERT(previous_base == assumed_cwdh_offset - first_cwdh_offset);
 | 
				
			||||||
 | 
					    ASSERT(previous_base == assumed_tglp_offset - first_tglp_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u32 offset = new_address - previous_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reset pointer back to start of sections and do the actual rebase
 | 
				
			||||||
 | 
					    current_offset = SharedFontStartOffset + cfnt.header_size;
 | 
				
			||||||
 | 
					    for (unsigned block = 0; block < cfnt.num_blocks; ++block) {
 | 
				
			||||||
 | 
					        u8* data = shared_font->GetPointer(current_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SectionHeader section_header;
 | 
				
			||||||
 | 
					        memcpy(§ion_header, data, sizeof(section_header));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (memcmp(section_header.magic, "FINF", 4) == 0) {
 | 
				
			||||||
            BCFNT::FINF finf;
 | 
					            BCFNT::FINF finf;
 | 
				
			||||||
            memcpy(&finf, data, sizeof(finf));
 | 
					            memcpy(&finf, data, sizeof(finf));
 | 
				
			||||||
            section_size = finf.section_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Relocate the offsets in the FINF section
 | 
					            // Relocate the offsets in the FINF section
 | 
				
			||||||
            finf.cmap_offset += new_address - previous_address;
 | 
					            finf.cmap_offset += offset;
 | 
				
			||||||
            finf.cwdh_offset += new_address - previous_address;
 | 
					            finf.cwdh_offset += offset;
 | 
				
			||||||
            finf.tglp_offset += new_address - previous_address;
 | 
					            finf.tglp_offset += offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memcpy(data, &finf, sizeof(finf));
 | 
					            memcpy(data, &finf, sizeof(finf));
 | 
				
			||||||
        } else if (memcmp(data, "CMAP", 4) == 0) {
 | 
					        } else if (memcmp(section_header.magic, "CMAP", 4) == 0) {
 | 
				
			||||||
            BCFNT::CMAP cmap;
 | 
					            BCFNT::CMAP cmap;
 | 
				
			||||||
            memcpy(&cmap, data, sizeof(cmap));
 | 
					            memcpy(&cmap, data, sizeof(cmap));
 | 
				
			||||||
            section_size = cmap.section_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Relocate the offsets in the CMAP section
 | 
					            // Relocate the offsets in the CMAP section
 | 
				
			||||||
            cmap.next_cmap_offset += new_address - previous_address;
 | 
					            cmap.next_cmap_offset += offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memcpy(data, &cmap, sizeof(cmap));
 | 
					            memcpy(data, &cmap, sizeof(cmap));
 | 
				
			||||||
        } else if (memcmp(data, "CWDH", 4) == 0) {
 | 
					        } else if (memcmp(section_header.magic, "CWDH", 4) == 0) {
 | 
				
			||||||
            BCFNT::CWDH cwdh;
 | 
					            BCFNT::CWDH cwdh;
 | 
				
			||||||
            memcpy(&cwdh, data, sizeof(cwdh));
 | 
					            memcpy(&cwdh, data, sizeof(cwdh));
 | 
				
			||||||
            section_size = cwdh.section_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Relocate the offsets in the CWDH section
 | 
					            // Relocate the offsets in the CWDH section
 | 
				
			||||||
            cwdh.next_cwdh_offset += new_address - previous_address;
 | 
					            cwdh.next_cwdh_offset += offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memcpy(data, &cwdh, sizeof(cwdh));
 | 
					            memcpy(data, &cwdh, sizeof(cwdh));
 | 
				
			||||||
        } else if (memcmp(data, "TGLP", 4) == 0) {
 | 
					        } else if (memcmp(section_header.magic, "TGLP", 4) == 0) {
 | 
				
			||||||
            BCFNT::TGLP tglp;
 | 
					            BCFNT::TGLP tglp;
 | 
				
			||||||
            memcpy(&tglp, data, sizeof(tglp));
 | 
					            memcpy(&tglp, data, sizeof(tglp));
 | 
				
			||||||
            section_size = tglp.section_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Relocate the offsets in the TGLP section
 | 
					            // Relocate the offsets in the TGLP section
 | 
				
			||||||
            tglp.sheet_data_offset += new_address - previous_address;
 | 
					            tglp.sheet_data_offset += offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memcpy(data, &tglp, sizeof(tglp));
 | 
					            memcpy(data, &tglp, sizeof(tglp));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data += section_size;
 | 
					        current_offset += section_header.section_size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,11 @@ struct CFNT {
 | 
				
			|||||||
    u32_le num_blocks;
 | 
					    u32_le num_blocks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SectionHeader {
 | 
				
			||||||
 | 
					    u8 magic[4];
 | 
				
			||||||
 | 
					    u32_le section_size;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct FINF {
 | 
					struct FINF {
 | 
				
			||||||
    u8 magic[4];
 | 
					    u8 magic[4];
 | 
				
			||||||
    u32_le section_size;
 | 
					    u32_le section_size;
 | 
				
			||||||
@ -75,12 +80,13 @@ struct CWDH {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Relocates the internal addresses of the BCFNT Shared Font to the new base.
 | 
					 * Relocates the internal addresses of the BCFNT Shared Font to the new base. The current base will
 | 
				
			||||||
 | 
					 * be auto-detected based on the file headers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @param shared_font SharedMemory object that contains the Shared Font
 | 
					 * @param shared_font SharedMemory object that contains the Shared Font
 | 
				
			||||||
 * @param previous_address Previous address at which the offsets in the structure were based.
 | 
					 | 
				
			||||||
 * @param new_address New base for the offsets in the structure.
 | 
					 * @param new_address New base for the offsets in the structure.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr previous_address, VAddr new_address);
 | 
					void RelocateSharedFont(Kernel::SharedPtr<Kernel::SharedMemory> shared_font, VAddr new_address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace BCFNT
 | 
					} // namespace BCFNT
 | 
				
			||||||
} // namespace APT
 | 
					} // namespace APT
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user