From 327201519a9a425cda41791590b1dbbeb3ae915e Mon Sep 17 00:00:00 2001 From: camezaro-intc Date: Thu, 8 Oct 2026 00:36:52 -0600 Subject: [PATCH] feat(font): implement sceFontDettachDeviceCacheBuffer Detach the device cache buffer attached by sceFontAttachDeviceCacheBuffer. The signature is taken from the IDA type database of Orbital: it takes the library, a pointer to receive the buffer and a pointer to receive its size. When no cache buffer is attached, it reports NOT_ATTACHED_CACHE_BUFFER. If the library allocated the buffer itself and no buffer pointer is passed, the memory is freed. The owned bit is cleared and device_cache_buf is reset to null. --- core/libs/prx/libSceFont/src/Library.cpp | 23 +++++++++++++++ .../libs/prx/libSceFont/src/Unimplemented.cpp | 4 --- core/libs/tests/GuestFont.cpp | 29 +++++++++++++++++++ docs/dev/TechnicalDebt.md | 1 + 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/core/libs/prx/libSceFont/src/Library.cpp b/core/libs/prx/libSceFont/src/Library.cpp index 90f5cc8b1..e872a3fa6 100644 --- a/core/libs/prx/libSceFont/src/Library.cpp +++ b/core/libs/prx/libSceFont/src/Library.cpp @@ -367,6 +367,29 @@ int APS5_VABI sceFontClearDeviceCache(FontLibrary library) { return rc; } +int APS5_VABI sceFontDettachDeviceCacheBuffer(FontLibrary library, void** buffer, std::uint32_t* size) { + auto* lib = static_cast(library); + if (!lib || lib->magic != LIBRARY_MAGIC) return SCE_FONT_ERROR_INVALID_LIBRARY; + std::uint32_t previous = 0; + if (!AcquireLibraryLock(lib, previous)) return SCE_FONT_ERROR_INVALID_LIBRARY; + std::uint32_t* current = AcquireDeviceCache(lib); + if (!current) { + ReleaseDeviceCache(lib, nullptr); + ReleaseLibraryLock(lib, previous); + return SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER; + } + if (size) *size = current[0]; + if (buffer) { + *buffer = current; + } else if ((lib->flags & 1u) != 0) { + lib->iface->dealloc(lib->alloc_ctx, current); + } + lib->flags &= ~1u; + ReleaseDeviceCache(lib, nullptr); + ReleaseLibraryLock(lib, previous); + return SCE_FONT_OK; +} + int APS5_VABI sceFontSupportExternalFonts(FontLibrary library, std::uint32_t fontMax, std::uint32_t formats) { return SupportFonts(library, &FontLibNative::external_fonts_ctx, fontMax, (fontMax << 6) | 0x20u, formats); } diff --git a/core/libs/prx/libSceFont/src/Unimplemented.cpp b/core/libs/prx/libSceFont/src/Unimplemented.cpp index 5b9c76ac6..87c3bbcd5 100644 --- a/core/libs/prx/libSceFont/src/Unimplemented.cpp +++ b/core/libs/prx/libSceFont/src/Unimplemented.cpp @@ -62,10 +62,6 @@ int APS5_VABI sceFontDestroyWords() { return 0; } -int APS5_VABI sceFontDettachDeviceCacheBuffer() { - NotImplemented_nid_no_patch(__func__); - return 0; -} int APS5_VABI sceFontGetAttribute() { NotImplemented_nid_no_patch(__func__); diff --git a/core/libs/tests/GuestFont.cpp b/core/libs/tests/GuestFont.cpp index be6cde4e7..97e814da7 100644 --- a/core/libs/tests/GuestFont.cpp +++ b/core/libs/tests/GuestFont.cpp @@ -16,6 +16,9 @@ int APS5_VABI sceFontDestroyLibrary(FontLibrary*); int APS5_VABI sceFontCreateRenderer(const FontMemory*, const void*, FontRenderer*); int APS5_VABI sceFontDestroyRenderer(FontRenderer*); int APS5_VABI sceFontGetPixelResolution(FontLibrary, std::uint32_t*); +int APS5_VABI sceFontAttachDeviceCacheBuffer(FontLibrary, void*, std::uint32_t); +int APS5_VABI sceFontClearDeviceCache(FontLibrary); +int APS5_VABI sceFontDettachDeviceCacheBuffer(FontLibrary, void**, std::uint32_t*); int APS5_VABI sceFontSupportSystemFonts(FontLibrary); int APS5_VABI sceFontSupportExternalFonts(FontLibrary, std::uint32_t, std::uint32_t); int APS5_VABI sceFontOpenFontSet(FontLibrary, std::uint32_t, std::uint32_t, const FontOpenDetail*, FontHandle*); @@ -144,6 +147,32 @@ int main() { Require(sceFontGetPixelResolution(coarseLibrary, &subPixelCount) == SCE_FONT_ERROR_INVALID_LIBRARY && subPixelCount == 0); Require(sceFontDestroyLibrary(&coarseLibrary) == SCE_FONT_OK && coarseLibrary == nullptr); + void* cacheBuffer = nullptr; + std::uint32_t cacheSize = 0; + Require(sceFontDettachDeviceCacheBuffer(nullptr, &cacheBuffer, &cacheSize) == SCE_FONT_ERROR_INVALID_LIBRARY); + Require(sceFontDettachDeviceCacheBuffer(¬ALibrary, &cacheBuffer, &cacheSize) == SCE_FONT_ERROR_INVALID_LIBRARY); + Require(sceFontClearDeviceCache(library) == SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER); + Require(sceFontDettachDeviceCacheBuffer(library, &cacheBuffer, &cacheSize) == SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER); + + std::vector callerCache(0x2000); + Require(sceFontAttachDeviceCacheBuffer(library, callerCache.data(), 0x1000) == SCE_FONT_ERROR_INVALID_PARAMETER); + Require(sceFontAttachDeviceCacheBuffer(library, callerCache.data(), static_cast(callerCache.size())) == SCE_FONT_OK); + Require(sceFontAttachDeviceCacheBuffer(library, callerCache.data(), static_cast(callerCache.size())) == SCE_FONT_ERROR_ALREADY_ATTACHED); + Require(sceFontClearDeviceCache(library) == SCE_FONT_OK); + Require(sceFontDettachDeviceCacheBuffer(library, &cacheBuffer, &cacheSize) == SCE_FONT_OK && cacheBuffer == callerCache.data() && cacheSize == callerCache.size()); + Require(sceFontDettachDeviceCacheBuffer(library, &cacheBuffer, &cacheSize) == SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER); + + Require(sceFontAttachDeviceCacheBuffer(library, nullptr, 0x2000) == SCE_FONT_OK); + cacheBuffer = nullptr; + cacheSize = 0; + Require(sceFontDettachDeviceCacheBuffer(library, &cacheBuffer, &cacheSize) == SCE_FONT_OK && cacheBuffer != nullptr && cacheSize == 0x2000); + Release(nullptr, cacheBuffer); + Require(sceFontDettachDeviceCacheBuffer(library, &cacheBuffer, &cacheSize) == SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER); + + Require(sceFontAttachDeviceCacheBuffer(library, nullptr, 0x2000) == SCE_FONT_OK); + Require(sceFontDettachDeviceCacheBuffer(library, nullptr, nullptr) == SCE_FONT_OK); + Require(sceFontDettachDeviceCacheBuffer(library, nullptr, nullptr) == SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER); + FontHandle font = reinterpret_cast(&memory); Require(sceFontOpenFontSet(library, SystemFontSet, 1, nullptr, &font) == SCE_FONT_ERROR_NO_SUPPORT_FUNCTION && font == nullptr); Require(sceFontSupportSystemFonts(library) == SCE_FONT_OK); diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 7b9455c33..ab59227e4 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -75,6 +75,7 @@ Throughout the project, every function at every stage either **does exactly what - [AMPR markers](../../core/libs/prx/libSceAmpr/Export.cpp) (libSceAmpr) - signatures taken from the [ampr_emu](https://github.com/drakmor/ampr_emu) reimplementation, not confirmed on a title: `sceAmprCommandBufferSetMarkerWithColor` takes the color by pointer, the push and measure variants by value. Colors are not recorded - [sceFontGetRenderScaledKerning](../../core/libs/prx/libSceFont/src/Render.cpp) (libSceFont) - arguments, the cleared output and the bound renderer check taken from `cellFontGetRenderScaledKerning` in [RPCS3](https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/cellFont.cpp) (PS3 predecessor of the library), not confirmed on a title. The kerning is the `sceFontGetKerning` one at the render scale - [sceFontGetPixelResolution](../../core/libs/prx/libSceFont/src/Library.cpp) (libSceFont) - signature taken from the IDA type database of [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json), not confirmed on a title. The value is the one the library's driver reports (64 for FreeType); the argument checks and the cleared output follow `sceFontGetLibrary` +- [sceFontDettachDeviceCacheBuffer](../../core/libs/prx/libSceFont/src/Library.cpp) (libSceFont) - signature taken from the IDA type database of [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json), not confirmed on a title. It detaches the cache buffer attached by `sceFontAttachDeviceCacheBuffer`, returns the buffer and its size, and reports `SCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFER` when no cache buffer is attached - [sceFontGetFontGlyphsCount, sceFontGetCharGlyphCode](../../core/libs/prx/libSceFont/src/Open.cpp) (libSceFont) - signatures taken from the IDA type database of [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json) and matching the [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Font/SceFont.Engine.cs) bindings, not confirmed on a title. The count is the face's glyph count and the glyph code its glyph index, as the library's driver reports them; a code with no glyph returns `NO_SUPPORT_GLYPH` and code 0 `NO_SUPPORT_CODE`, as `sceFontRenderCharGlyphImage` does. The argument checks and the cleared output follow `sceFontGetPixelResolution` - [sceFontGetFontResolution](../../core/libs/prx/libSceFont/src/Open.cpp) (libSceFont) - signature taken from the IDA type database of [Orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json), not confirmed on a title; the outputs are inferred from the names. The resolution is the face's units per EM and the scale pixel the driver's face scale (units per EM / 64 for FreeType), the pixel scale a font has when opened. Either output may be null, as in `sceFontGetResolutionDpi` - [sceFontCreateWritingLine, sceFontWritingLineWritesOrder](../../core/libs/prx/libSceFont/src/WritingLine.cpp) (libSceFont) - signatures and the `SceFontWritingLineStep`/`SceFontCreateWritingLineDetail` layouts (detail id `0x0FD5`) taken from [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Font/SceFontStructs.cs), not confirmed on a title; the meaning of the 64-bit writing attribute is unknown