Skip to content

feat(libSceFont): implement sceFontCharactersRefersTextCodes and text code stepping - #6019

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
KernelPanicNT:feat/libscefont-text-codes
Oct 17, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
KernelPanicNT:feat/libscefont-text-codes

Conversation

@KernelPanicNT

@KernelPanicNT KernelPanicNT commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What

Implements sceFontCharactersRefersTextCodes, sceFontTextCodesStepNext and sceFontTextCodesStepBack, the three remaining text-code exports of libSceFont, over the character chain sceFontCreateString already builds.

Prior art. #4050 by @p3n1cillin implemented the same three functions with the same PS4 11.00 rules (the rules @fma-rc reported from the disassembly in its review) and was closed by a maintainer for two reasons: no title was shown to call them, and the behaviour comes from the PS4 library only. Both reasons still apply to this PR, which follows the same rules and names no title either. It was written from that disassembly comment, not from the #4050 branch, and differs from it in a FontTextCodes union over systemUse[8] instead of named cursor fields, a null text character that throws instead of returning null, and tests added to the existing guest_font suite. The reasons #1014 and #4865 were closed (no title confirmed to call these functions, no known executable importing them) apply to it as well. The earlier attempts by @renzipego-cpu, @Thomas73737, @tarfouss3 and @Dripl1x, and why each was closed, are listed under the duplicate check below.

Source of the behaviour.

  • Traversal: the PS4 11.00 libSceFont.sprx disassembly of these NIDs that @fma-rc posted in the review of #4050. This is PS4 behaviour; no PS5 source is known. The repo already prefers PS4 measurements over KytyPS5 for libSceFont (see the sceFontWritingLineGetOrderingSpace and sceFontCharacterGetSyllableStringState debt entries, both measured on PS4 11.00 libSceFont.sprx).
    • Refers (0x15f80) never compares the character with the term, keeps the current character at cursor +0x28, the start at +0x30 and the term at +0x38, and returns null for a character whose byte +0x31 (clusterIndex) or +0x33 (synthetic) is set.
    • StepNext (0x15fd0) compares the current character with the term (cmp 0x38(%rax),%rcx) before advancing, so it returns null at the term after visiting it: over A B C with C as term it yields B, then C, then null. The report says it returns null only at the term; null at the end of the chain (for example with a null term, as one test uses) is assumed here and not covered by the report.
    • StepBack (0x16020) returns null when the current character is the start (cmp 0x30(%rax),%rcx), so a cursor created at B does not step back to A. Null at the head of the chain is assumed here and not covered by the report.
    • Both steps skip characters whose byte +0x33 is set.
  • Signatures: Orbital's IDA type database, sceFontCharactersRefersTextCodes(textCharacter, termCharacter, textCodes*) and sceFontTextCodesStepBack / sceFontTextCodesStepNext(textCodesStep); the same three in SharpProspero.
  • Layout: SharpProspero's SceFontTextCodes, 64 bytes with the order pointer at 0 and the 32-bit code at 8; the new FontTextCodes union (text.order, text.code, text.reserved over systemUse[8]) has a static_assert on its size, and the cursor words at +0x28/+0x30/+0x38 are systemUse[5..7].
  • Null pointers: a null output or step returns null, as in KytyPS5 (the commit already cited for sceFontWritingRefersRenderStepCharacter); the disassembly report does not cover them.

Changes:

  • FontTypes.hpp: adds the 64-byte FontTextCodes union.
  • Text.cpp: the three exports as above; a step that returns null leaves the codes unchanged.
  • Unimplemented.cpp: the three throwing stubs are removed.
  • guest_font: walks a three-character string forward and back and checks order and code at each step, the term being visited, the stop at the start character, a cursor whose start is its term, skipped synthetic characters, null Refers for clustered and synthetic characters, null output and null step, untouched codes after a null result, and the throwing null character.
  • core/libs/prx/libSceFont/CMakeLists.txt: guest_font_tests gets configure_windows_unwind, like guest_system_font_tests and guest_font_writing_line_tests, so the exception the test expects from the null text character reaches it on Windows instead of terminating the process.
  • docs/dev/debt/libSceFont.md: records the sources and that the rules are PS4 ones.

Still throwing (std::runtime_error): a null text character, whose console result is not covered by the disassembly report. The other unimplemented libSceFont exports are not touched.

Progress: libSceFont 120/195 → 123/195 (tools/progress.py).

Tested

Head cf762829d1ba0cbe6278653a96300c53447a5dda, base e27ff7c545cb5ac669612567d853956ffa02ebe6.

  • Linux (Ubuntu 24.04, GCC 14.2.0, Ninja, Release, BUILD_TESTING=ON, AMD EPYC 7763 (GitHub Codespaces), tests run natively): guest_font_tests passes in 5 of 5 runs, the test executable being run directly five times.
  • Negative control: keep the tests and replace only core/libs/prx/libSceFont/src/Text.cpp, core/libs/prx/libSceFont/src/Unimplemented.cpp with the base version: guest_font_tests fails with sceFontCharactersRefersTextCodes not implemented. Restoring the PR source and rebuilding, guest_font_tests passes in 5 of 5 runs again.
  • Windows, full Build workflow on my fork (run 38618151303), this head built together with the other queued branches and merged into the fork's main at 2b7e3ce69fd889deceb6b52ac1fbf13e7c0d1084, WinLibs MinGW-w64 GCC 15.2.0, Release, BUILD_TESTING=ON: 1212/1212 tests pass; the relinker (Linux, Windows, macOS), register-context and write-watch jobs of the same run also pass.
  • Conventions checker and git diff --check pass. The Linux job of the Build workflow now targets the project's self-hosted runner, so it was not run on the fork; no title was run.

Duplicate and overlap check

Checklist

  • Based on e27ff7c54; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes (Claude)

🤖 Generated with Claude Code

… code stepping

sceFontCharactersRefersTextCodes fills a 64-byte FontTextCodes with the
order and code of a text character and keeps the current, start and
term characters at +0x28, +0x30 and +0x38. The traversal follows the
PS4 11.00 libSceFont.sprx disassembly posted in the review of boykopovar#4050,
which implemented the same rules: Refers never compares the character
with the term and returns null for a clustered or synthetic character,
sceFontTextCodesStepNext returns null at the term after visiting it,
sceFontTextCodesStepBack returns null at the start character, and both
steps skip synthetic characters. Null from StepNext at the end of the
chain and from StepBack at the head of the chain is assumed and not
covered by the report.

The signatures follow Orbital's IDA type database and SharpProspero. A
null cursor or output returns null as in KytyPS5; a null text character
throws. guest_font_tests gets configure_windows_unwind so the expected
exception reaches the test on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Progress report (19fc5a8 → cf76282)

📈 System libraries: 88.77% (+0.08%, +3 implemented functions)

✅ 3 implemented
Library Name
libSceFont sceFontCharactersRefersTextCodes
libSceFont sceFontTextCodesStepBack
libSceFont sceFontTextCodesStepNext

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 6044 core/libs/prx/libSceFont/CMakeLists.txt
core/libs/tests/GuestFont.cpp

@adriadam10 adriadam10 self-assigned this Oct 16, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked build and ctest (guest_font and the libSceFont/libs scope, all green), the new test fails to build without the source change, signatures/layout against Orbital and SharpProspero, the PS4 11.00 traversal rules, and that the assumptions not covered by the disassembly are recorded in docs/dev/debt/libSceFont.md; merging.

@adriadam10
adriadam10 merged commit 8566bec into boykopovar:main Oct 17, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants