diff --git a/src/core/libraries/font/font.cpp b/src/core/libraries/font/font.cpp index 8164ebff9..437eddb8f 100644 --- a/src/core/libraries/font/font.cpp +++ b/src/core/libraries/font/font.cpp @@ -4,14 +4,21 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include #include #include #include #include #include "common/logging/log.h" +#include "common/singleton.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/font/font.h" #include "core/libraries/libs.h" @@ -21,7 +28,13 @@ #define STB_TRUETYPE_IMPLEMENTATION #include "externals/dear_imgui/imstb_truetype.h" +namespace Libraries::Font { +struct FontLibOpaque; +} + namespace { +Core::FileSys::MntPoints* g_mnt = Common::Singleton::Instance(); + struct GlyphEntry { std::vector bitmap; int w = 0; @@ -62,6 +75,10 @@ struct LibraryState { bool support_external = false; u32 external_formats = 0; u32 external_fontMax = 0; + const Libraries::Font::OrbisFontMem* backing_memory = nullptr; + Libraries::Font::OrbisFontLibCreateParams create_params = nullptr; + u64 edition = 0; + Libraries::Font::FontLibOpaque* native = nullptr; }; static std::unordered_map g_library_state; @@ -73,14 +90,67 @@ static FontState& GetState(Libraries::Font::OrbisFontHandle h) { return g_font_state[h]; } +static FontState* TryGetState(Libraries::Font::OrbisFontHandle h) { + if (!h) + return nullptr; + auto it = g_font_state.find(h); + if (it == g_font_state.end()) + return nullptr; + return &it->second; +} + static LibraryState& GetLibState(Libraries::Font::OrbisFontLib lib) { return g_library_state[lib]; } +static void RemoveLibState(Libraries::Font::OrbisFontLib lib) { + g_library_state.erase(lib); +} + static void LogExternalFormatSupport(u32 formats_mask) { LOG_INFO(Lib_Font, "ExternalFormatsMask=0x{:X}", formats_mask); } +static std::filesystem::path ResolveGuestPath(const char* guest_path) { + if (!guest_path) { + return {}; + } + if (guest_path[0] != '/') { + return std::filesystem::path(guest_path); + } + if (!g_mnt) { + return {}; + } + return g_mnt->GetHostPath(guest_path); +} + +static bool LoadGuestFileBytes(const std::filesystem::path& host_path, + std::vector& out_bytes) { + std::ifstream file(host_path, std::ios::binary | std::ios::ate); + if (!file) { + return false; + } + const std::streamoff size = file.tellg(); + if (size < 0) { + return false; + } + if (size == 0) { + out_bytes.clear(); + return true; + } + if (static_cast(size) > std::numeric_limits::max()) { + return false; + } + out_bytes.resize(static_cast(size)); + file.seekg(0, std::ios::beg); + if (!file.read(reinterpret_cast(out_bytes.data()), + static_cast(out_bytes.size()))) { + out_bytes.clear(); + return false; + } + return true; +} + enum class ScaleMode { AscenderHeight, EmSquare, @@ -189,9 +259,42 @@ static inline void LogStrideOnce(const Libraries::Font::OrbisFontRenderSurface* namespace Libraries::Font { -struct FontLibOpaque {}; +struct FontLibOpaque { + u16 magic; + u16 reserved0; + u32 lock_word; + u32 flags; + u8 reserved1[0x14]; + void* alloc_ctx; + void** alloc_vtbl; + u8 reserved2[0x50]; + void* sys_driver; + void* fontset_registry; + u8 reserved3[0x10]; + void* sysfonts_ctx; + void* external_fonts_ctx; + u32* device_cache_buf; +}; +static_assert(sizeof(FontLibOpaque) == 0xB8, "FontLibOpaque size"); +static_assert(offsetof(FontLibOpaque, alloc_ctx) == 0x20, "FontLibOpaque alloc_ctx offset"); +static_assert(offsetof(FontLibOpaque, alloc_vtbl) == 0x28, "FontLibOpaque alloc_vtbl offset"); +static_assert(offsetof(FontLibOpaque, sys_driver) == 0x80, "FontLibOpaque sys_driver offset"); +static_assert(offsetof(FontLibOpaque, fontset_registry) == 0x88, + "FontLibOpaque fontset_registry offset"); +static_assert(offsetof(FontLibOpaque, sysfonts_ctx) == 0xA0, "FontLibOpaque sysfonts_ctx offset"); +static_assert(offsetof(FontLibOpaque, external_fonts_ctx) == 0xA8, + "FontLibOpaque external_fonts_ctx offset"); +static_assert(offsetof(FontLibOpaque, device_cache_buf) == 0xB0, + "FontLibOpaque device_cache_buf offset"); struct OrbisFontRenderer_ {}; +static void* g_allocator_vtbl_stub[4] = {}; +static std::uint8_t g_sys_driver_stub{}; +static std::uint8_t g_fontset_registry_stub{}; +static std::uint8_t g_sysfonts_ctx_stub{}; +static std::uint8_t g_external_fonts_ctx_stub{}; +static u32 g_device_cache_stub{}; + s32 PS4_SYSV_ABI sceFontAttachDeviceCacheBuffer(OrbisFontLib library, void* buffer, u32 size) { LOG_ERROR(Lib_Font, "(STUBBED) called library={} buffer={} size={}", static_cast(library), static_cast(buffer), size); @@ -199,8 +302,13 @@ s32 PS4_SYSV_ABI sceFontAttachDeviceCacheBuffer(OrbisFontLib library, void* buff } s32 PS4_SYSV_ABI sceFontBindRenderer(OrbisFontHandle fontHandle, OrbisFontRenderer renderer) { + if (!fontHandle || !renderer) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } auto& st = GetState(fontHandle); st.bound_renderer = renderer; + LOG_INFO(Lib_Font, "BindRenderer: handle={} renderer={}", static_cast(fontHandle), + static_cast(renderer)); return ORBIS_OK; } @@ -325,9 +433,10 @@ s32 PS4_SYSV_ABI sceFontCreateGraphicsServiceWithEdition() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontCreateLibrary() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceFontCreateLibrary(const OrbisFontMem* memory, + OrbisFontLibCreateParams create_params, + OrbisFontLib* pLibrary) { + return sceFontCreateLibraryWithEdition(memory, create_params, 0, pLibrary); } s32 PS4_SYSV_ABI sceFontCreateLibraryWithEdition(const OrbisFontMem* memory, @@ -336,73 +445,83 @@ s32 PS4_SYSV_ABI sceFontCreateLibraryWithEdition(const OrbisFontMem* memory, if (!pLibrary) { return ORBIS_FONT_ERROR_INVALID_PARAMETER; } - (void)memory; - (void)create_params; - (void)edition; - *pLibrary = new FontLibOpaque{}; + if (!memory) { + return ORBIS_FONT_ERROR_INVALID_MEMORY; + } + auto* lib = new (std::nothrow) FontLibOpaque{}; + if (!lib) { + return ORBIS_FONT_ERROR_ALLOCATION_FAILED; + } + lib->magic = 0x0F01; + lib->lock_word = 0; + lib->flags = 0; + lib->alloc_ctx = const_cast(memory); + lib->alloc_vtbl = g_allocator_vtbl_stub; + lib->sys_driver = &g_sys_driver_stub; + lib->fontset_registry = &g_fontset_registry_stub; + lib->sysfonts_ctx = &g_sysfonts_ctx_stub; + lib->external_fonts_ctx = &g_external_fonts_ctx_stub; + lib->device_cache_buf = &g_device_cache_stub; + *pLibrary = lib; + auto& state = GetLibState(lib); + state = LibraryState{}; + state.backing_memory = memory; + state.create_params = create_params; + state.edition = edition; + state.native = lib; + LOG_INFO(Lib_Font, "CreateLibrary: memory={} selection={} edition={} -> lib={}", + static_cast(memory), static_cast(create_params), edition, + static_cast(*pLibrary)); return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontCreateRenderer() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceFontDestroyLibrary(OrbisFontLib* pLibrary) { + if (!pLibrary || !*pLibrary) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + auto lib = *pLibrary; + RemoveLibState(lib); + delete static_cast(lib); + *pLibrary = nullptr; + LOG_INFO(Lib_Font, "DestroyLibrary: lib={} destroyed", static_cast(lib)); return ORBIS_OK; } +s32 PS4_SYSV_ABI sceFontCreateRenderer(const OrbisFontMem* memory, + OrbisFontRendererCreateParams create_params, + OrbisFontRenderer* pRenderer) { + return sceFontCreateRendererWithEdition(memory, create_params, 0, pRenderer); +} + s32 PS4_SYSV_ABI sceFontCreateRendererWithEdition(const OrbisFontMem* memory, OrbisFontRendererCreateParams create_params, u64 edition, OrbisFontRenderer* pRenderer) { if (!pRenderer) { return ORBIS_FONT_ERROR_INVALID_PARAMETER; } - (void)memory; - (void)create_params; - (void)edition; - *pRenderer = new OrbisFontRenderer_{}; + if (!memory) { + return ORBIS_FONT_ERROR_INVALID_MEMORY; + } + auto* renderer = new (std::nothrow) OrbisFontRenderer_{}; + if (!renderer) { + return ORBIS_FONT_ERROR_ALLOCATION_FAILED; + } + *pRenderer = renderer; + LOG_INFO(Lib_Font, "CreateRenderer: memory={} selection={} edition={} renderer={}", + static_cast(memory), static_cast(create_params), edition, + static_cast(renderer)); return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontCreateString() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontCreateWords() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontCreateWritingLine() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontDefineAttribute() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontDeleteGlyph() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontDestroyGraphicsDevice() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontDestroyGraphicsService() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontDestroyLibrary() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceFontDestroyRenderer() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceFontDestroyRenderer(OrbisFontRenderer* pRenderer) { + if (!pRenderer || !*pRenderer) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + auto renderer = *pRenderer; + delete static_cast(renderer); + *pRenderer = nullptr; + LOG_INFO(Lib_Font, "DestroyRenderer: renderer={} destroyed", + static_cast(renderer)); return ORBIS_OK; } @@ -558,10 +677,14 @@ s32 PS4_SYSV_ABI sceFontGetGlyphExpandBufferState() { s32 PS4_SYSV_ABI sceFontGetHorizontalLayout(OrbisFontHandle fontHandle, OrbisFontHorizontalLayout* layout) { - if (!layout) { + if (!fontHandle || !layout) { return ORBIS_FONT_ERROR_INVALID_PARAMETER; } - auto& st = GetState(fontHandle); + auto* st_ptr = TryGetState(fontHandle); + if (!st_ptr) { + return ORBIS_FONT_ERROR_INVALID_FONT_HANDLE; + } + auto& st = *st_ptr; if (st.ext_face_ready) { if (st.ext_scale_for_height == 0.0f) st.ext_scale_for_height = stbtt_ScaleForPixelHeight(&st.ext_face, st.scale_h); @@ -637,9 +760,18 @@ s32 PS4_SYSV_ABI sceFontGetPixelResolution() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontGetRenderCharGlyphMetrics() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceFontGetRenderCharGlyphMetrics(OrbisFontHandle fontHandle, u32 codepoint, + OrbisFontGlyphMetrics* out_metrics) { + if (!fontHandle || !out_metrics) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + auto& st = GetState(fontHandle); + if (!st.bound_renderer) { + LOG_DEBUG(Lib_Font, "GetRenderCharGlyphMetrics: renderer not bound for handle={}", + static_cast(fontHandle)); + return ORBIS_FONT_ERROR_NOT_BOUND_RENDERER; + } + return sceFontGetCharGlyphMetrics(fontHandle, codepoint, out_metrics); } s32 PS4_SYSV_ABI sceFontGetRenderEffectSlant() { @@ -657,25 +789,34 @@ s32 PS4_SYSV_ABI sceFontGetRenderScaledKerning() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontGetRenderScalePixel(OrbisFontHandle fontHandle, float* w, float* h) { - auto& st = GetState(fontHandle); - if (w) - *w = st.scale_w; - if (h) - *h = st.scale_h; - if (!st.bound_renderer) { +s32 PS4_SYSV_ABI sceFontGetRenderScalePixel(OrbisFontHandle fontHandle, float* out_w, + float* out_h) { + if (!fontHandle || (!out_w && !out_h)) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + auto* st = TryGetState(fontHandle); + if (!st) { + return ORBIS_FONT_ERROR_INVALID_FONT_HANDLE; + } + if (out_w) + *out_w = st->scale_w; + if (out_h) + *out_h = st->scale_h; + if (!st->bound_renderer) { LOG_DEBUG(Lib_Font, "GetRenderScalePixel: no renderer bound; returning configured scale w={} h={}", - w ? *w : -1.0f, h ? *h : -1.0f); + out_w ? *out_w : -1.0f, out_h ? *out_h : -1.0f); } else { LOG_DEBUG(Lib_Font, "GetRenderScalePixel: handle={} -> w={}, h={}", - static_cast(fontHandle), w ? *w : -1.0f, h ? *h : -1.0f); + static_cast(fontHandle), out_w ? *out_w : -1.0f, + out_h ? *out_h : -1.0f); } return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontGetRenderScalePoint(OrbisFontHandle fontHandle, float* w, float* h) { - return sceFontGetRenderScalePixel(fontHandle, w, h); +s32 PS4_SYSV_ABI sceFontGetRenderScalePoint(OrbisFontHandle fontHandle, float* out_w, + float* out_h) { + return sceFontGetRenderScalePixel(fontHandle, out_w, out_h); } s32 PS4_SYSV_ABI sceFontGetResolutionDpi() { @@ -683,16 +824,21 @@ s32 PS4_SYSV_ABI sceFontGetResolutionDpi() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontGetScalePixel(OrbisFontHandle fontHandle, float* w, float* h) { - if (!w || !h) { +s32 PS4_SYSV_ABI sceFontGetScalePixel(OrbisFontHandle fontHandle, float* out_w, float* out_h) { + if (!fontHandle || (!out_w && !out_h)) { LOG_DEBUG(Lib_Font, "sceFontGetScalePixel: invalid params"); return ORBIS_FONT_ERROR_INVALID_PARAMETER; } - const auto& st = GetState(fontHandle); - *w = st.scale_w; - *h = st.scale_h; + auto* st = TryGetState(fontHandle); + if (!st) { + return ORBIS_FONT_ERROR_INVALID_FONT_HANDLE; + } + if (out_w) + *out_w = st->scale_w; + if (out_h) + *out_h = st->scale_h; LOG_DEBUG(Lib_Font, "GetScalePixel: handle={} -> w={}, h={}", - static_cast(fontHandle), *w, *h); + static_cast(fontHandle), out_w ? *out_w : -1.0f, out_h ? *out_h : -1.0f); return ORBIS_OK; } @@ -1049,27 +1195,69 @@ s32 PS4_SYSV_ABI sceFontGraphicsUpdateShapeFillPlot() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontMemoryInit(OrbisFontMem* fontMemory, void* address, u32 sizeByte, - const OrbisFontMemInterface* memInterface, void* mspaceObject, - OrbisFontMemDestroyCb destroyCallback, void* destroyObject) { - LOG_ERROR(Lib_Font, - "(STUBBED) called font_mem={} region_base={} sizeByte={} mem_if={} mspace_handle={}" - " destroy_cb={} destroy_ctx={}", - static_cast(fontMemory), static_cast(address), sizeByte, - static_cast(memInterface), static_cast(mspaceObject), - reinterpret_cast(destroyCallback), - static_cast(destroyObject)); +s32 PS4_SYSV_ABI sceFontMemoryInit(OrbisFontMem* mem_desc, void* region_addr, u32 region_size, + const OrbisFontMemInterface* iface, void* mspace_obj, + OrbisFontMemDestroyCb destroy_cb, void* destroy_ctx) { + if (!mem_desc) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + + mem_desc->mem_kind = 0; + mem_desc->attr_bits = 0; + mem_desc->region_base = region_addr; + mem_desc->region_size = region_size; + mem_desc->iface = iface; + mem_desc->mspace_handle = mspace_obj; + mem_desc->on_destroy = destroy_cb; + mem_desc->destroy_ctx = destroy_ctx; + mem_desc->some_ctx1 = nullptr; + mem_desc->some_ctx2 = nullptr; + + LOG_INFO( + Lib_Font, + "FontMemoryInit: font_mem={} region_base={} size={} mspace={} mem_if_set={} destroy_cb={}", + static_cast(mem_desc), static_cast(region_addr), region_size, + static_cast(mem_desc->mspace_handle), iface != nullptr, + reinterpret_cast(destroy_cb)); return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontMemoryTerm() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceFontMemoryTerm(OrbisFontMem* mem_desc) { + if (!mem_desc) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + if (mem_desc->on_destroy) { + mem_desc->on_destroy(mem_desc, mem_desc->destroy_ctx, mem_desc->some_ctx1); + } + std::memset(mem_desc, 0, sizeof(*mem_desc)); + LOG_INFO(Lib_Font, "FontMemoryTerm: font_mem={} cleaned", static_cast(mem_desc)); return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontOpenFontFile() { - LOG_ERROR(Lib_Font, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceFontOpenFontFile(OrbisFontLib library, const char* guest_path, u32 open_mode, + const OrbisFontOpenParams* open_detail, + OrbisFontHandle* out_handle) { + if (!library || !guest_path || !out_handle) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + const auto host_path = ResolveGuestPath(guest_path); + const std::filesystem::path path_to_open = + host_path.empty() ? std::filesystem::path(guest_path) : host_path; + + std::vector file_bytes; + if (!LoadGuestFileBytes(path_to_open, file_bytes)) { + LOG_WARNING(Lib_Font, "OpenFontFile: failed to open '{}'", path_to_open.string()); + return ORBIS_FONT_ERROR_FS_OPEN_FAILED; + } + if (file_bytes.size() > std::numeric_limits::max()) { + LOG_WARNING(Lib_Font, "OpenFontFile: '{}' exceeds libSceFont size limit ({} bytes)", + path_to_open.string(), file_bytes.size()); + return ORBIS_FONT_ERROR_FS_OPEN_FAILED; + } + LOG_INFO(Lib_Font, "OpenFontFile: path='{}' size={} openMode={}", path_to_open.string(), + static_cast(file_bytes.size()), open_mode); + return sceFontOpenFontMemory(library, file_bytes.data(), static_cast(file_bytes.size()), + open_detail, out_handle); } s32 PS4_SYSV_ABI sceFontOpenFontInstance() { @@ -1185,7 +1373,15 @@ s32 PS4_SYSV_ABI sceFontOpenFontSet(OrbisFontLib library, u32 fontSetType, u32 o } s32 PS4_SYSV_ABI sceFontRebindRenderer(OrbisFontHandle fontHandle) { - LOG_ERROR(Lib_Font, "(STUBBED) called fontHandle={}", static_cast(fontHandle)); + if (!fontHandle) { + return ORBIS_FONT_ERROR_INVALID_PARAMETER; + } + auto& st = GetState(fontHandle); + if (!st.bound_renderer) { + return ORBIS_FONT_ERROR_NOT_BOUND_RENDERER; + } + LOG_INFO(Lib_Font, "RebindRenderer: handle={} renderer={}", + static_cast(fontHandle), static_cast(st.bound_renderer)); return ORBIS_OK; } @@ -1649,10 +1845,14 @@ s32 PS4_SYSV_ABI sceFontSetResolutionDpi() { } s32 PS4_SYSV_ABI sceFontSetScalePixel(OrbisFontHandle fontHandle, float w, float h) { - if (w <= 0.0f || h <= 0.0f) { + if (!fontHandle || w <= 0.0f || h <= 0.0f) { return ORBIS_FONT_ERROR_INVALID_PARAMETER; } - auto& st = GetState(fontHandle); + auto* st_ptr = TryGetState(fontHandle); + if (!st_ptr) { + return ORBIS_FONT_ERROR_INVALID_FONT_HANDLE; + } + auto& st = *st_ptr; st.scale_w = w; st.scale_h = h; if (st.ext_face_ready) diff --git a/src/core/libraries/font/font.h b/src/core/libraries/font/font.h index 7846232ec..84c7230d4 100644 --- a/src/core/libraries/font/font.h +++ b/src/core/libraries/font/font.h @@ -204,11 +204,15 @@ s32 PS4_SYSV_ABI sceFontControl(); s32 PS4_SYSV_ABI sceFontCreateGraphicsDevice(); s32 PS4_SYSV_ABI sceFontCreateGraphicsService(); s32 PS4_SYSV_ABI sceFontCreateGraphicsServiceWithEdition(); -s32 PS4_SYSV_ABI sceFontCreateLibrary(); +s32 PS4_SYSV_ABI sceFontCreateLibrary(const OrbisFontMem* memory, + OrbisFontLibCreateParams create_params, + OrbisFontLib* pLibrary); s32 PS4_SYSV_ABI sceFontCreateLibraryWithEdition(const OrbisFontMem* memory, OrbisFontLibCreateParams create_params, u64 edition, OrbisFontLib* pLibrary); -s32 PS4_SYSV_ABI sceFontCreateRenderer(); +s32 PS4_SYSV_ABI sceFontCreateRenderer(const OrbisFontMem* memory, + OrbisFontRendererCreateParams create_params, + OrbisFontRenderer* pRenderer); s32 PS4_SYSV_ABI sceFontCreateRendererWithEdition(const OrbisFontMem* memory, OrbisFontRendererCreateParams create_params, u64 edition, OrbisFontRenderer* pRenderer); @@ -219,8 +223,8 @@ s32 PS4_SYSV_ABI sceFontDefineAttribute(); s32 PS4_SYSV_ABI sceFontDeleteGlyph(); s32 PS4_SYSV_ABI sceFontDestroyGraphicsDevice(); s32 PS4_SYSV_ABI sceFontDestroyGraphicsService(); -s32 PS4_SYSV_ABI sceFontDestroyLibrary(); -s32 PS4_SYSV_ABI sceFontDestroyRenderer(); +s32 PS4_SYSV_ABI sceFontDestroyLibrary(OrbisFontLib* pLibrary); +s32 PS4_SYSV_ABI sceFontDestroyRenderer(OrbisFontRenderer* pRenderer); s32 PS4_SYSV_ABI sceFontDestroyString(); s32 PS4_SYSV_ABI sceFontDestroyWords(); s32 PS4_SYSV_ABI sceFontDestroyWritingLine(); @@ -244,14 +248,15 @@ s32 PS4_SYSV_ABI sceFontGetKerning(OrbisFontHandle fontHandle, u32 preCode, u32 OrbisFontKerning* kerning); s32 PS4_SYSV_ABI sceFontGetLibrary(OrbisFontHandle fontHandle, OrbisFontLib* pLibrary); s32 PS4_SYSV_ABI sceFontGetPixelResolution(); -s32 PS4_SYSV_ABI sceFontGetRenderCharGlyphMetrics(); +s32 PS4_SYSV_ABI sceFontGetRenderCharGlyphMetrics(OrbisFontHandle fontHandle, u32 codepoint, + OrbisFontGlyphMetrics* out_metrics); s32 PS4_SYSV_ABI sceFontGetRenderEffectSlant(); s32 PS4_SYSV_ABI sceFontGetRenderEffectWeight(); s32 PS4_SYSV_ABI sceFontGetRenderScaledKerning(); -s32 PS4_SYSV_ABI sceFontGetRenderScalePixel(OrbisFontHandle fontHandle, float* w, float* h); -s32 PS4_SYSV_ABI sceFontGetRenderScalePoint(OrbisFontHandle fontHandle, float* w, float* h); +s32 PS4_SYSV_ABI sceFontGetRenderScalePixel(OrbisFontHandle fontHandle, float* out_w, float* out_h); +s32 PS4_SYSV_ABI sceFontGetRenderScalePoint(OrbisFontHandle fontHandle, float* out_w, float* out_h); s32 PS4_SYSV_ABI sceFontGetResolutionDpi(); -s32 PS4_SYSV_ABI sceFontGetScalePixel(OrbisFontHandle fontHandle, float* w, float* h); +s32 PS4_SYSV_ABI sceFontGetScalePixel(OrbisFontHandle fontHandle, float* out_w, float* out_h); s32 PS4_SYSV_ABI sceFontGetScalePoint(); s32 PS4_SYSV_ABI sceFontGetScriptLanguage(); s32 PS4_SYSV_ABI sceFontGetTypographicDesign(); @@ -320,11 +325,13 @@ s32 PS4_SYSV_ABI sceFontGraphicsUpdateRotation(); s32 PS4_SYSV_ABI sceFontGraphicsUpdateScaling(); s32 PS4_SYSV_ABI sceFontGraphicsUpdateShapeFill(); s32 PS4_SYSV_ABI sceFontGraphicsUpdateShapeFillPlot(); -s32 PS4_SYSV_ABI sceFontMemoryInit(OrbisFontMem* fontMemory, void* address, u32 sizeByte, - const OrbisFontMemInterface* memInterface, void* mspaceObject, - OrbisFontMemDestroyCb destroyCallback, void* destroyObject); -s32 PS4_SYSV_ABI sceFontMemoryTerm(); -s32 PS4_SYSV_ABI sceFontOpenFontFile(); +s32 PS4_SYSV_ABI sceFontMemoryInit(OrbisFontMem* mem_desc, void* region_addr, u32 region_size, + const OrbisFontMemInterface* iface, void* mspace_obj, + OrbisFontMemDestroyCb destroy_cb, void* destroy_ctx); +s32 PS4_SYSV_ABI sceFontMemoryTerm(OrbisFontMem* mem_desc); +s32 PS4_SYSV_ABI sceFontOpenFontFile(OrbisFontLib library, const char* guest_path, u32 open_mode, + const OrbisFontOpenParams* open_detail, + OrbisFontHandle* out_handle); s32 PS4_SYSV_ABI sceFontOpenFontInstance(); s32 PS4_SYSV_ABI sceFontOpenFontMemory(OrbisFontLib library, const void* fontAddress, u32 fontSize, const OrbisFontOpenParams* open_params, diff --git a/src/core/libraries/font/fontft.cpp b/src/core/libraries/font/fontft.cpp index 4a1dbb989..d997c46f3 100644 --- a/src/core/libraries/font/fontft.cpp +++ b/src/core/libraries/font/fontft.cpp @@ -8,6 +8,38 @@ namespace Libraries::FontFt { +namespace { +bool g_library_selected = false; +bool g_renderer_selected = false; + +constexpr OrbisFontLibrarySelection kDefaultLibrarySelection{0xF2000000u, 0, nullptr, nullptr}; + +static void* PS4_SYSV_ABI RendererCreateStub() { + LOG_ERROR(Lib_FontFt, "(STUBBED) renderer create called"); + return nullptr; +} + +static void PS4_SYSV_ABI RendererQueryStub() { + LOG_ERROR(Lib_FontFt, "(STUBBED) renderer query called"); +} + +static void PS4_SYSV_ABI RendererDestroyStub() { + LOG_ERROR(Lib_FontFt, "(STUBBED) renderer destroy called"); +} + +static OrbisFontRendererSelection MakeRendererSelection() { + OrbisFontRendererSelection sel{}; + sel.magic = 0xF2000000u; + sel.size = 0x168; + sel.create_fn = reinterpret_cast(&RendererCreateStub); + sel.query_fn = reinterpret_cast(&RendererQueryStub); + sel.destroy_fn = reinterpret_cast(&RendererDestroyStub); + return sel; +} + +static const OrbisFontRendererSelection kDefaultRendererSelection = MakeRendererSelection(); +} // namespace + s32 PS4_SYSV_ABI sceFontFtInitAliases() { LOG_ERROR(Lib_FontFt, "(STUBBED) called"); return ORBIS_OK; @@ -103,14 +135,28 @@ s32 PS4_SYSV_ABI sceFontSelectGlyphsFt() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceFontSelectLibraryFt() { - LOG_ERROR(Lib_FontFt, "(STUBBED) called"); - return ORBIS_OK; +const OrbisFontLibrarySelection* PS4_SYSV_ABI sceFontSelectLibraryFt(int value) { + if (!g_library_selected) { + g_library_selected = true; + LOG_INFO(Lib_FontFt, "SelectLibraryFt: using default FreeType shim"); + } + LOG_INFO(Lib_FontFt, "SelectLibraryFt: value={}", value); + if (value == 0) { + return &kDefaultLibrarySelection; + } + return nullptr; } -s32 PS4_SYSV_ABI sceFontSelectRendererFt() { - LOG_ERROR(Lib_FontFt, "(STUBBED) called"); - return ORBIS_OK; +const OrbisFontRendererSelection* PS4_SYSV_ABI sceFontSelectRendererFt(int value) { + if (!g_renderer_selected) { + g_renderer_selected = true; + LOG_INFO(Lib_FontFt, "SelectRendererFt: using stb_truetype renderer backend"); + } + LOG_INFO(Lib_FontFt, "SelectRendererFt: value={}", value); + if (value == 0) { + return &kDefaultRendererSelection; + } + return nullptr; } void RegisterlibSceFontFt(Core::Loader::SymbolsResolver* sym) { @@ -137,4 +183,4 @@ void RegisterlibSceFontFt(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("Xx974EW-QFY", "libSceFontFt", 1, "libSceFontFt", sceFontSelectRendererFt); }; -} // namespace Libraries::FontFt \ No newline at end of file +} // namespace Libraries::FontFt diff --git a/src/core/libraries/font/fontft.h b/src/core/libraries/font/fontft.h index cec6d7872..a94e83102 100644 --- a/src/core/libraries/font/fontft.h +++ b/src/core/libraries/font/fontft.h @@ -11,6 +11,21 @@ class SymbolsResolver; namespace Libraries::FontFt { +struct OrbisFontLibrarySelection { + u32 magic; + u32 reserved; + void* reserved_ptr1; + void* reserved_ptr2; +}; + +struct OrbisFontRendererSelection { + u32 magic; + u32 size; + uintptr_t create_fn; + uintptr_t query_fn; + uintptr_t destroy_fn; +}; + s32 PS4_SYSV_ABI sceFontFtInitAliases(); s32 PS4_SYSV_ABI sceFontFtSetAliasFont(); s32 PS4_SYSV_ABI sceFontFtSetAliasPath(); @@ -30,8 +45,8 @@ s32 PS4_SYSV_ABI sceFontFtSupportType42(); s32 PS4_SYSV_ABI sceFontFtSupportWinFonts(); s32 PS4_SYSV_ABI sceFontFtTermAliases(); s32 PS4_SYSV_ABI sceFontSelectGlyphsFt(); -s32 PS4_SYSV_ABI sceFontSelectLibraryFt(); -s32 PS4_SYSV_ABI sceFontSelectRendererFt(); +const OrbisFontLibrarySelection* PS4_SYSV_ABI sceFontSelectLibraryFt(int value); +const OrbisFontRendererSelection* PS4_SYSV_ABI sceFontSelectRendererFt(int value); void RegisterlibSceFontFt(Core::Loader::SymbolsResolver* sym); -} // namespace Libraries::FontFt \ No newline at end of file +} // namespace Libraries::FontFt