mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 22:25:41 +12:00
107 lines
No EOL
3.6 KiB
C++
107 lines
No EOL
3.6 KiB
C++
// Copyright 2016 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
// Adapted from https://github.com/PabloMK7/citra/blob/master/src/core/hle/service/apt/bcfnt/bcfnt.cpp
|
|
|
|
#include "services/fonts.hpp"
|
|
|
|
namespace HLE::Fonts {
|
|
void relocateSharedFont(u8* sharedFont, u32 newAddress) {
|
|
constexpr u32 sharedFontStartOffset = 0x80;
|
|
const u8* cfntData = &sharedFont[sharedFontStartOffset];
|
|
|
|
CFNT cfnt;
|
|
std::memcpy(&cfnt, cfntData, sizeof(cfnt));
|
|
|
|
u32 assumedCmapOffset = 0;
|
|
u32 assumedCwdhOffset = 0;
|
|
u32 assumedTglpOffset = 0;
|
|
u32 firstCmapOffset = 0;
|
|
u32 firstCwdhOffset = 0;
|
|
u32 firstTglpOffset = 0;
|
|
|
|
// First discover the location of sections so that the rebase offset can be auto-detected
|
|
u32 currentOffset = sharedFontStartOffset + cfnt.headerSize;
|
|
for (uint block = 0; block < cfnt.numBlocks; ++block) {
|
|
const u8* data = &sharedFont[currentOffset];
|
|
|
|
SectionHeader sectionHeader;
|
|
std::memcpy(§ionHeader, data, sizeof(sectionHeader));
|
|
|
|
if (firstCmapOffset == 0 && std::memcmp(sectionHeader.magic, "CMAP", 4) == 0) {
|
|
firstCmapOffset = currentOffset;
|
|
} else if (firstCwdhOffset == 0 && std::memcmp(sectionHeader.magic, "CWDH", 4) == 0) {
|
|
firstCwdhOffset = currentOffset;
|
|
} else if (firstTglpOffset == 0 && std::memcmp(sectionHeader.magic, "TGLP", 4) == 0) {
|
|
firstTglpOffset = currentOffset;
|
|
} else if (std::memcmp(sectionHeader.magic, "FINF", 4) == 0) {
|
|
Fonts::FINF finf;
|
|
std::memcpy(&finf, data, sizeof(finf));
|
|
|
|
assumedCmapOffset = finf.cmapOffset - sizeof(SectionHeader);
|
|
assumedCwdhOffset = finf.cwdhOffset - sizeof(SectionHeader);
|
|
assumedTglpOffset = finf.tglpOffset - sizeof(SectionHeader);
|
|
}
|
|
|
|
currentOffset += sectionHeader.sectionSize;
|
|
}
|
|
|
|
u32 previousBase = assumedCmapOffset - firstCmapOffset;
|
|
if ((previousBase != assumedCwdhOffset - firstCwdhOffset) || (previousBase != assumedTglpOffset - firstTglpOffset)) {
|
|
Helpers::warn("You shouldn't be seeing this. Shared Font file offsets might be borked?");
|
|
}
|
|
|
|
u32 offset = newAddress - previousBase;
|
|
|
|
// Reset pointer back to start of sections and do the actual rebase
|
|
currentOffset = sharedFontStartOffset + cfnt.headerSize;
|
|
for (uint block = 0; block < cfnt.numBlocks; ++block) {
|
|
u8* data = &sharedFont[currentOffset];
|
|
|
|
SectionHeader sectionHeader;
|
|
std::memcpy(§ionHeader, data, sizeof(sectionHeader));
|
|
|
|
if (std::memcmp(sectionHeader.magic, "FINF", 4) == 0) {
|
|
Fonts::FINF finf;
|
|
std::memcpy(&finf, data, sizeof(finf));
|
|
|
|
// Relocate the offsets in the FINF section
|
|
finf.cmapOffset += offset;
|
|
finf.cwdhOffset += offset;
|
|
finf.tglpOffset += offset;
|
|
|
|
std::memcpy(data, &finf, sizeof(finf));
|
|
} else if (std::memcmp(sectionHeader.magic, "CMAP", 4) == 0) {
|
|
Fonts::CMAP cmap;
|
|
std::memcpy(&cmap, data, sizeof(cmap));
|
|
|
|
// Relocate the offsets in the CMAP section
|
|
if (cmap.nextCmapOffset != 0) {
|
|
cmap.nextCmapOffset += offset;
|
|
}
|
|
|
|
std::memcpy(data, &cmap, sizeof(cmap));
|
|
} else if (std::memcmp(sectionHeader.magic, "CWDH", 4) == 0) {
|
|
Fonts::CWDH cwdh;
|
|
std::memcpy(&cwdh, data, sizeof(cwdh));
|
|
|
|
// Relocate the offsets in the CWDH section
|
|
if (cwdh.nextCwdhOffset != 0) {
|
|
cwdh.nextCwdhOffset += offset;
|
|
}
|
|
|
|
std::memcpy(data, &cwdh, sizeof(cwdh));
|
|
} else if (std::memcmp(sectionHeader.magic, "TGLP", 4) == 0) {
|
|
Fonts::TGLP tglp;
|
|
std::memcpy(&tglp, data, sizeof(tglp));
|
|
|
|
// Relocate the offsets in the TGLP section
|
|
tglp.sheetDataOffset += offset;
|
|
std::memcpy(data, &tglp, sizeof(tglp));
|
|
}
|
|
|
|
currentOffset += sectionHeader.sectionSize;
|
|
}
|
|
}
|
|
} // namespace HLE::Fonts
|