Skip to content

feat(libSceIcu): implement the enumeration dispatch exports - #11132

Merged
oneandonlydean merged 31 commits into
boykopovar:mainfrom
mantavisual:feat/icu-enumeration-dispatch
Nov 4, 2026
Merged

oneandonlydean merged 31 commits into
boykopovar:mainfrom
mantavisual:feat/icu-enumeration-dispatch

Conversation

@mantavisual

Copy link
Copy Markdown
Contributor

What

Implements the four uenum_ exports that firmware 13.42's libSceIcu has (BunnyFl's export list): uenum_close, uenum_count, uenum_next and uenum_unext. They don't enumerate anything themselves. They dispatch through the callbacks in a UEnumeration, the object ICU's enumeration producers return; 13.42 exports producers such as ucal_openTimeZones, ucol_getKeywordValues and ucurr_openISOCurrencies.

Behaviour follows ICU 78.1's uenum.cpp over the UEnumeration layout in uenumimp.h: baseContext, context, then the close, count, uNext, next and reset callbacks, 56 bytes. The callbacks are called with the guest ABI (APS5_VABI), so an enumeration built by guest code or by a future producer here works the same way.

  • uenum_count, uenum_next and uenum_unext return −1 or null for a null enumeration without reading the status, and for an error that is already set without calling anything. If the callback is missing, they set U_UNSUPPORTED_ERROR. Otherwise they return whatever the callback returns, and the callback may change the status.
  • uenum_next passes a local length slot when the caller gives a null resultLength. uenum_unext forwards the null as ICU does.
  • uenum_close does nothing for null. With a close callback, it frees baseContext (if set) and then calls close. Without one, it frees only the enumeration. Freeing uses the guest free, because ICU's uprv_free defaults to free and 13.42 exports no u_setMemoryFunctions to change it.

A null status with a nonnull enumeration throws APS5_INVALID_ARG_EX, since ICU dereferences it. uenum_reset and the *Default helpers are not in 13.42's exports and are not added. The new debt entry records this, and that no export here creates an enumeration yet.

Depends on #11122 (stacked on it). The agreed ICU order is #11013 → #10961 → … → #10967 → #11088 → #11115 → #11118 → #11122, and this PR comes after #11122. Until those merge, the diff also shows their commits. This PR's own change is the last commit, c1d9fa2f64.

Tested

Windows 11 Pro 23H2, WinLibs GCC 15.2.0 r7, Release, BUILD_TESTING=ON, on #11122 (0bcb2ae1aa).

  • New guest_icu_enumeration, using enumerations whose callbacks are APS5_VABI functions:
    • Dispatch of count (the callback's status change is kept), next with and without a length slot, unext (including a forwarded null length), the end of the enumeration, and close.
    • Every short-circuit: a set error, a null enumeration (including with a null status), and missing callbacks (U_UNSUPPORTED_ERROR, with the length left alone).
    • Freeing with a counting application allocator: with a close callback, only baseContext is freed and close is called. Without one, only the enumeration is freed and its baseContext is left alone, as in ICU.
    • The null-status rejections.
  • ctest -R "guest_icu_|patched_libraries": all 7 pass. The NID-patched libSceIcu.prx builds.
  • tools/progress.py --module libSceIcu: 50 implemented, 0 stubs. tools/check_test_registration.py build: 1346 test executables, none built and not run.
  • python3 tools/check_conventions.py --base origin/main passes. Overlap: no open PR implements or names any uenum_ function (checked 2026-10-25).

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 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: feat(libSceIcu): implement the code point set exports #11122
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

mantavisual and others added 10 commits October 25, 2026 19:29
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Progress report (89a7f98 → 0570125)

📈 System libraries: 26.8% (+0.09%, +45 implemented functions)

✅ 45 implemented
Library Name
libSceIcu u_errorName_nid_postfix
libSceIcu u_getVersion_nid_postfix
libSceIcu ucfpos_close_nid_postfix
libSceIcu ucfpos_constrainCategory_nid_postfix
libSceIcu ucfpos_constrainField_nid_postfix
libSceIcu ucfpos_getCategory_nid_postfix
libSceIcu ucfpos_getField_nid_postfix
libSceIcu ucfpos_getIndexes_nid_postfix
libSceIcu ucfpos_open_nid_postfix
libSceIcu uenum_close_nid_postfix
libSceIcu uenum_count_nid_postfix
libSceIcu uenum_next_nid_postfix
libSceIcu uenum_unext_nid_postfix
libSceIcu uprv_add32_overflow_nid_postfix
libSceIcu uprv_ceil_nid_postfix
libSceIcu uprv_fabs_nid_postfix
libSceIcu uprv_floor_nid_postfix
libSceIcu uprv_fmax_nid_postfix
libSceIcu uprv_fmin_nid_postfix
libSceIcu uprv_fmod_nid_postfix
libSceIcu uprv_getInfinity_nid_postfix
libSceIcu uprv_getNaN_nid_postfix
libSceIcu uprv_isInfinite_nid_postfix
libSceIcu uprv_isNaN_nid_postfix
libSceIcu uprv_isNegativeInfinity_nid_postfix
libSceIcu uprv_isPositiveInfinity_nid_postfix
libSceIcu uprv_log_nid_postfix
libSceIcu uprv_maxMantissa_nid_postfix
libSceIcu uprv_max_nid_postfix
libSceIcu uprv_maximumPtr_nid_postfix
libSceIcu uprv_min_nid_postfix
libSceIcu uprv_modf_nid_postfix
libSceIcu uprv_mul32_overflow_nid_postfix
libSceIcu uprv_pow10_nid_postfix
libSceIcu uprv_pow_nid_postfix
libSceIcu uprv_round_nid_postfix
libSceIcu uprv_trunc_nid_postfix
libSceIcu uset_addAll_nid_postfix
libSceIcu uset_addRange_nid_postfix
libSceIcu uset_add_nid_postfix
libSceIcu uset_close_nid_postfix
libSceIcu uset_contains_nid_postfix
libSceIcu uset_getItemCount_nid_postfix
libSceIcu uset_getItem_nid_postfix
libSceIcu uset_openEmpty_nid_postfix

Changed libraries (implemented exports)

Library Before After Change
libSceIcu 28/2480 (1.13%) 73/2525 (2.89%) +1.76%

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the PR-specific Enumeration.cpp and UEnumeration layout against pinned ICU 78.1 uenum.cpp/uenumimp.h. Null-enumeration and pre-set-error short circuits, missing-callback status, the next dummy length slot, unext null forwarding, and close/baseContext free ordering match the source. The callback types use the guest calling convention and the 56-byte layout matches ICU. I syntax-compiled the changed dispatcher and GuestIcuEnumeration.cpp locally with GCC 12.2 (g++ -std=c++20 -Icore/libs -fsyntax-only); the PR reports Windows guest_icu_enumeration and ctest -R "guest_icu_|patched_libraries" passing. Hosted eligibility, conventions, intake, labels and report pass; product build/test jobs are skipped. This is stacked on #11122, which remains a merge-order dependency.

@BunnyFl

BunnyFl commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

@mantavisual the four uenum_ exports here behave like firmware 13.42's libSceIcu.sprx, run natively the same way as in #11122, with Enumeration.cpp from c1d9fa2f64 compiled unchanged. Both sides get identical 56-byte enumerations whose callbacks and free record every call; this is the module's code on a PC, not a console.

  • 168 cases, every combination of: null or real enumeration; incoming status 0, 1, 16 or -128 (all but uenum_close); callbacks present or missing; null or real length pointer (next, unext); a callback that sets status 5; and for uenum_close, baseContext null or set. Each compares the return value, status, length and the call log. 0 mismatches, three identical runs.
  • What the module does in those cases, matched by the PR: a null enumeration or a failure status returns -1 / null without calling anything, and a warning (-128) doesn't stop the call. A missing callback sets U_UNSUPPORTED_ERROR (16). uenum_next passes a non-null length pointer to the callback when the caller passes null; uenum_unext passes the null on. uenum_close frees baseContext before calling close; without a close callback it frees only the enumeration, not baseContext.
  • Controls: copies of Enumeration.cpp with one change each are caught: close called before baseContext is freed, next passing the null length on, 1 instead of 16 for a missing callback, a warning treated as failure, and baseContext freed when there is no close callback.
  • Not covered: a null status pointer with a real enumeration. The callbacks on the PR side use the host calling convention, since APS5_VABI is empty in this build.

The debt entry's "13.42 exports no u_setMemoryFunctions" holds: no module in the 13.42 dump exports it, or uprv_malloc, uprv_realloc or uprv_free, under the plain names or with _50 to _89 suffixes.

@wachi35676

Copy link
Copy Markdown
Contributor

Tested head c1d9fa2f64 merged onto main d31f372e33 on WSL2 Ubuntu 24.04 (GCC 13.3, LP64), BUILD_TESTING=ON. This adds the Linux run.

  • The guest_icu* tests registered at this head (6) pass 3 of 3 runs on Linux. The same 6 pass 3 of 3 on Windows 11 (WinLibs GCC 15.2.0).

AI-assisted: yes (Claude Code); results above were run on this machine.

oneandonlydean added a commit to oneandonlydean/AnyPS5 that referenced this pull request Oct 27, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 27, 2026
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 10963 core/libs/prx/libSceIcu/CMakeLists.txt L1
PR 15346 core/libs/prx/libSceIcu/CMakeLists.txt L1

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 10964 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 10965 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 10966 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 10967 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 12320 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 12738 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 13486 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 13578 core/libs/prx/libSceIcu/CMakeLists.txt
core/libs/prx/libSceIcu/libSceIcu.hpp
docs/dev/debt/libSceIcu.md
PR 14212 docs/dev/debt/libSceIcu.md

…field-position

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
#	docs/dev/debt/libSceIcu.md
…-point-sets

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
#	docs/dev/debt/libSceIcu.md
…patch

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
#	docs/dev/debt/libSceIcu.md
…ric-helpers

# Conflicts:
#	core/libs/prx/libSceIcu/libSceIcu.hpp
#	docs/dev/debt/libSceIcu.md
…rror-name

# Conflicts:
#	core/libs/prx/libSceIcu/Version.cpp
#	core/libs/prx/libSceIcu/Version.hpp
#	core/libs/prx/libSceIcu/libSceIcu.hpp
…field-position

# Conflicts:
#	core/libs/prx/libSceIcu/libSceIcu.hpp
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 1, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
oneandonlydean and others added 6 commits November 3, 2026 01:02
# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
…ric-helpers

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

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
#	docs/dev/debt/libSceIcu.md
…rror-name

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

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
…field-position

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

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
…-point-sets

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

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
#	docs/dev/debt/libSceIcu.md
…patch

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

# Conflicts:
#	core/libs/prx/libSceIcu/CMakeLists.txt
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@oneandonlydean
oneandonlydean merged commit 6b89e1b into boykopovar:main Nov 4, 2026
12 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.

5 participants