Skip to content

Commit

Permalink
Implement shared font relocation
Browse files Browse the repository at this point in the history
  • Loading branch information
wheremyfoodat committed Oct 22, 2024
1 parent 238d84b commit 8c80099
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 9 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ set(SERVICE_SOURCE_FILES src/core/services/service_manager.cpp src/core/services
src/core/services/act.cpp src/core/services/nfc.cpp src/core/services/dlp_srvr.cpp
src/core/services/ir_user.cpp src/core/services/http.cpp src/core/services/soc.cpp
src/core/services/ssl.cpp src/core/services/news_u.cpp src/core/services/amiibo_device.cpp
src/core/services/csnd.cpp src/core/services/nwm_uds.cpp
src/core/services/csnd.cpp src/core/services/nwm_uds.cpp src/core/services/fonts.cpp
)
set(PICA_SOURCE_FILES src/core/PICA/gpu.cpp src/core/PICA/regs.cpp src/core/PICA/shader_unit.cpp
src/core/PICA/shader_interpreter.cpp src/core/PICA/dynapica/shader_rec.cpp
Expand Down Expand Up @@ -326,14 +326,14 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/audio/hle_core.hpp include/capstone.hpp include/audio/aac.hpp include/PICA/pica_frag_config.hpp
include/PICA/pica_frag_uniforms.hpp include/PICA/shader_gen_types.hpp include/PICA/shader_decompiler.hpp
include/PICA/pica_vert_config.hpp include/sdl_sensors.hpp include/PICA/draw_acceleration.hpp include/renderdoc.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp
)

cmrc_add_resource_library(
resources_console_fonts
NAMESPACE ConsoleFonts
WHENCE "src/core/services/fonts/"
"src/core/services/fonts/CitraSharedFontUSRelocated.bin"
"src/core/services/fonts/SharedFontReplacement.bin"
)

set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp
Expand Down
2 changes: 1 addition & 1 deletion include/PICA/dynapica/pica_recs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "helpers.hpp"
#include "vertex_loader_rec.hpp"

// Common file for our PICA JITs (From vertex config -> CPU assembly and from PICA shader -> CPU assembly)
// Common file for our PICA JITs (From PICA shader -> CPU assembly)

namespace Dynapica {
#ifdef PANDA3DS_DYNAPICA_SUPPORTED
Expand Down
2 changes: 1 addition & 1 deletion include/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,5 @@ class Memory {

bool allocateMainThreadStack(u32 size);
Regions getConsoleRegion();
void copySharedFont(u8* ptr);
void copySharedFont(u8* ptr, u32 vaddr);
};
84 changes: 84 additions & 0 deletions include/services/fonts.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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.h

#pragma once

#include <memory>

#include "helpers.hpp"
#include "swap.hpp"

namespace HLE::Fonts {
struct CFNT {
u8 magic[4];
u16_le endianness;
u16_le headerSize;
u32_le version;
u32_le fileSize;
u32_le numBlocks;
};

struct SectionHeader {
u8 magic[4];
u32_le sectionSize;
};

struct FINF {
u8 magic[4];
u32_le sectionSize;
u8 fontType;
u8 lineFeed;
u16_le alterCharIndex;
u8 default_width[3];
u8 encoding;
u32_le tglpOffset;
u32_le cwdhOffset;
u32_le cmapOffset;
u8 height;
u8 width;
u8 ascent;
u8 reserved;
};

struct TGLP {
u8 magic[4];
u32_le sectionSize;
u8 cellWidth;
u8 cellHeight;
u8 baselinePosition;
u8 maxCharacterWidth;
u32_le sheetSize;
u16_le numSheets;
u16_le sheetImageFormat;
u16_le numColumns;
u16_le numRows;
u16_le sheetWidth;
u16_le sheetHeight;
u32_le sheetDataOffset;
};

struct CMAP {
u8 magic[4];
u32_le sectionSize;
u16_le codeBegin;
u16_le codeEnd;
u16_le mappingMethod;
u16_le reserved;
u32_le nextCmapOffset;
};

struct CWDH {
u8 magic[4];
u32_le sectionSize;
u16_le startIndex;
u16_le endIndex;
u32_le nextCwdhOffset;
};

// 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.
void relocateSharedFont(u8* sharedFont, u32 newAddress);
} // namespace HLE::Fonts
2 changes: 1 addition & 1 deletion src/core/kernel/memory_management.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void Kernel::mapMemoryBlock() {
break;

case KernelHandles::FontSharedMemHandle:
mem.copySharedFont(ptr);
mem.copySharedFont(ptr, addr);
break;

case KernelHandles::CSNDSharedMemHandle:
Expand Down
10 changes: 7 additions & 3 deletions src/core/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "config_mem.hpp"
#include "resource_limits.hpp"
#include "services/fonts.hpp"
#include "services/ptm.hpp"

CMRC_DECLARE(ConsoleFonts);
Expand Down Expand Up @@ -51,7 +52,7 @@ void Memory::reset() {
if (e.handle == KernelHandles::FontSharedMemHandle) {
// Read font size from the cmrc filesystem the font is stored in
auto fonts = cmrc::ConsoleFonts::get_filesystem();
e.size = fonts.open("CitraSharedFontUSRelocated.bin").size();
e.size = fonts.open("SharedFontReplacement.bin").size();
}

e.mapped = false;
Expand Down Expand Up @@ -520,10 +521,13 @@ Regions Memory::getConsoleRegion() {
return region;
}

void Memory::copySharedFont(u8* pointer) {
void Memory::copySharedFont(u8* pointer, u32 vaddr) {
auto fonts = cmrc::ConsoleFonts::get_filesystem();
auto font = fonts.open("CitraSharedFontUSRelocated.bin");
auto font = fonts.open("SharedFontReplacement.bin");
std::memcpy(pointer, font.begin(), font.size());

// Relocate shared font to the address it's being loaded to
HLE::Fonts::relocateSharedFont(pointer, vaddr);
}

std::optional<u64> Memory::getProgramID() {
Expand Down
107 changes: 107 additions & 0 deletions src/core/services/fonts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// 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(&sectionHeader, 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(&sectionHeader, 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

0 comments on commit 8c80099

Please sign in to comment.