Skip to content

feat(libc): implement llroundf - #2933

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
reyani-dev:feat/libc-llroundf
Oct 10, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
reyani-dev:feat/libc-llroundf

Conversation

@reyani-dev

Copy link
Copy Markdown
Contributor

Resubmission of #2189, which was closed because no title was shown stopping on it. The title evidence has since been posted there by @babyhuey (run):

On main c963432, OpenRCT2 Native Port (PPSA99728) stops at llroundf (eQhBFnTOp40): Windows FAIL: unresolved ELF import eQhBFnTOp40 (llroundf) from libSceLibcInternal.prx, Linux undefined symbol: eQhBFnTOp40. With this change it moves on to atol.

The function is still absent on current main, and no open PR implements it. The branch is rebased onto current main. Windows 11 (WinLibs GCC 15.2.0), Release: guest_math passes 3/3, check_conventions.py passes, and pr_overlap.py reports no overlap.


What

Exports llroundf next to lroundf and llround, which round the same way: halfway cases away from zero, into a 64-bit result.

Title: PPSA99169 RetroArch imports it from libSceLibcInternal (resolved through libc.prx), per the #1578 audit. I haven't run the title.

Tested

Windows 11, WinLibs GCC 15.2.0 r7, Release, -DBUILD_TESTING=ON:

  • New checks in guest_math_tests, next to the llround case:
    • halfway cases away from zero (±2.5f);
    • -0.4f → 0;
    • results beyond 32 bits (2^33, -2^62);
    • 0.49999997f → 0, which floor(x + 0.5f) gets wrong because the sum rounds up to 1;
    • 16777215.f.
  • Mutation check: floor(x + 0.5f) and the host lround (32-bit long on Windows) each make guest_math fail.
  • cmake --build build --target libs: the patched libc.prx exports eQhBFnTOp40.
  • tools/check_conventions.py passes, and tools/pr_overlap.py --branch reports no overlap.

Checklist

  • Based on current main; 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 in TechnicalDebt
  • 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
  • AI-assisted: yes

🤖 Generated with Claude Code

Export it next to lroundf and llround, rounding halfway cases away
from zero into the 64-bit guest long long.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@reyani-dev reyani-dev mentioned this pull request Oct 10, 2026
9 tasks done
@reyani-dev

Copy link
Copy Markdown
Contributor Author

Full Linux and Windows builds and tests for this head (3c431989), using the project's Build workflow. I can't start the upstream manual run, so I ran the same build.yml in my fork through a mirror PR. Like the upstream run, the jobs check out the PR head merged into current main (bf6e25a1):

Job Result
linux success; full build, ctest: 703/703 passed
windows success; full build, ctest: 711/711 passed
relinker (Linux, Windows, macOS) success

Run: https://github.com/AchrafReyani/AnyPS5/actions/runs/38076401894

@github-actions github-actions Bot added the libc label Oct 10, 2026
@github-actions

Copy link
Copy Markdown

Progress report (1476f76 → 3c43198)

➖ System libraries: 84.56% (+0.0%, +1 implemented functions)

✅ 1 implemented
Library Name
libc llroundf_nid_postfix

@babyhuey

Copy link
Copy Markdown
Contributor

Heads-up so the evidence here isn't read against the wrong layout: the runs of mine linked in the description are from main c963432, before #2605. Since #2605 each title's sce_module/libc.prx has to be unwrapped, and that module is the SDK shim whose exports point 1872 libc functions at one return-0 stub (#2652). So on current main (9c5d67f, catalog run with the module unwrapped) OpenRCT2 Native Port (PPSA99728) stops at execvp (#2827) instead of llroundf. The stop comes back once the shim's return-0 exports are left out, which is what the closed #2705 did; a run without the shim's return-0 exports would show whether llroundf is its stop again.

@reyani-dev

Copy link
Copy Markdown
Contributor Author

Thanks @babyhuey, that's an important caveat. These titles' imports declare libSceLibcInternal, so on current main they bind to the bundled SDK shim's return-0 export (#1497/#2652) instead of failing at load, which hides the stop. Once #1529 keeps libSceLibcInternal-declared imports host-bound, the stop comes back, as the closed #2705 table showed. Either way, these titles call the real function, so on main they currently get 0 from it.

@oneandonlydean
oneandonlydean merged commit 230ce25 into boykopovar:main Oct 10, 2026
15 checks passed
MarcZX10 added a commit to MarcZX10/AnyPS5 that referenced this pull request Oct 11, 2026
The original fix predates llroundf, which was added in boykopovar#2933. Use the same guest range and exception behavior for the fourth wrapper and include it in the edge-case checks.
MarcZX10 added a commit to MarcZX10/AnyPS5 that referenced this pull request Oct 11, 2026
The original fix predates llroundf, which was added in boykopovar#2933. Use the same guest range and exception behavior for the fourth wrapper and include it in the edge-case checks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants