Repository navigation
feat(libSceCesCs): encode UCS-2, UTF-8, UTF-16 and UTF-32 characters into any MBCS profile - #9175
Conversation
Progress report (941ace5 → 12e3082)📈 System libraries: 48.92% (+0.06%, +8 implemented functions) ✅ 8 implemented
Changed libraries (implemented exports)
|
|
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.
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.
|
|
Windows run of 524c49e merged onto Built |
MarcZX10
left a comment
There was a problem hiding this comment.
Review
I reviewed the new eight forwarding exports and the added MBCS round-trip/error cases. I did not find a correctness issue in the new wrappers. The reported test coverage is strong: exhaustive BMP checks across profiles, round trips, invalid UTF cases, output preservation on failure, Windows coverage, and hosted test runs.
Branch freshness
This head is 635 commits behind current main (merge base 27bcd6a29e). Its five commits are the stack #8967 → #8972 → #8976 → #8993 → this PR; the four prerequisite PRs are still open. Please keep the stack based on current main as required by CONTRIBUTING and rerun the focused guest_ces* tests after updating it. The test results in the description are from the earlier base c020ce893.
Overlap coordination
The overlap report lists open #9107 in Export.cpp, PendingExports.cpp, and the debt file. You already identify #9107 as nearby, distinct work, but the repo rule asks contributors to agree with overlapping authors on landing order. Please record that agreement and add a Depends on entry if this PR is actually stacked on it. The report also lists #8923 for the same debt-file line; please note that documentation-only overlap in the PR description. I found no evidence that these PRs duplicate the eight exports here.
Checks
git diff --checkagainst currentmain: passed.tools/check_conventions.py --base upstream/main --head refs/review/9175: passed.- Current CI: eligibility, intake, conventions, labels, and report passed; Linux, Windows, register-context, relinker, ASan relinker, and write-watch jobs were skipped.
- I did not rebuild locally in this session; the extensive test results above are author-reported on the older base.
The top commit’s implementation and test design look sound. I’ll revisit after the stack is current and the overlap order is recorded.
524c49e to
a0dd95f
Compare
|
Rebased onto current |
a0dd95f to
880dce7
Compare
|
Rebased onto current |
880dce7 to
be0749d
Compare
|
Rebased again onto current |
be0749d to
1f48265
Compare
|
Rebased onto current |
1f48265 to
d494b14
Compare
|
Rebased onto current |
d494b14 to
8ccc8df
Compare
|
Pushed @orezraey heads-up since #10186 carries this branch: I left the Shift-JIS U+0080-U+009F |
|
Windows run of
Not run: a title. AI-assisted: yes (Claude Code) |
8ccc8df to
f9581c8
Compare
…into any MBCS profile
f9581c8 to
12e3082
Compare
|
Rebased onto current
All 14 |
|
Windows run of
Not run: a title. AI-assisted: yes (Claude Code) |
|
@ycbuzi thanks for the Windows run on the rebased head, and for the control run. I've added it to the Tested section. |
Dismissing a stale review: the requested changes were addressed after it (new head) and the merge queue blocks on it. Please request changes again if anything is still open.
|
Checked the eight |
What
Implements the 8 libSceCesCs exports that #8993 leaves throwing on the encode side:
sceCesUcs2ToMbc,sceCesUtf8ToMbc,sceCesUtf16ToMbc,sceCesUtf16beToMbc,sceCesUtf16leToMbc,sceCesUtf32ToMbc,sceCesUtf32beToMbcandsceCesUtf32leToMbc. Each converts one character into the profile it is given. simonbronk agreed on #8993 that I take this piece, so this branch carries the whole stack and only the top commit is new.sceCesUtf8ToSJisandsceCesUcs2ToGb: UCS-2 and native UTF-32 are passed by value, UTF-32be/le by pointer, and UTF-8/UTF-16 as a buffer with its size and an optional consumed-length pointer.scalarToProfiled,bufferToProfiledorutf32ToProfiled, the helpers behind the per-encoding*ToSJis,*ToEucJp,*ToGband*ToEucCnforms, withisMbcsas the profile check. That is the same checksceCesMbcTo*uses, so both directions accept the same profiles: Cp1250, Cp1251, Cp1252, CP932, CP51932, GBK, EUC-CN, EUC-KR, UHC and Big5. Each profile encodes through the existingencodeMbcsdispatch and its tables.INVALID_PARAMETER, then a null sourceINVALID_SRC_BUFFER, a zero source sizeSRC_BUFFER_END, a null outputINVALID_DST_BUFFER, then ill-formed inputINVALID_ENCODE(orSRC_BUFFER_ENDfor a cut sequence), a character the profile does not mapUNASSIGNED_CODE, and a short outputDST_BUFFER_END. Input UTF goes through the library's existingdecodeUtf8/decodeUtf16and the scalar check, which reject overlong UTF-8, surrogates and anything above U+10FFFF as Unicode 3.9 requires. Nothing is written on failure.sceCesMbcsUcsSetMbcsReplacementCharCodeandsceCesMbcsUcsSetMbcsReplacementCharUCode. The stack does not model a replacement character and its behaviour is unknown, so an unmapped character answersUNASSIGNED_CODEand is not replaced, as in the per-encoding forms.docs/dev/debt/libSceCesCs.mdto cover the encode direction, moved its unverified-errors sentence to the front, and changed the pending-exports count from 70 to 62. Nothing here is a console measurement.Overlap: #9107 (EUC-KR, UHC and Big5 scalar conversions) edits nearby lines in
Export.cpp,PendingExports.cppand the debt file but adds no*ToMbcexport, so whichever lands second will need a small rebase. #8923 doesn't touch these exports either.Measured on a PS5
I ran homebrew payloads on a PS5 that load the console's
libSceCesCs.sprxand callsceCesUtf32ToMbcon every value from U+0000 to U+110001 with each of the 15 MBCS profiles, andsceCesUcs2To*andsceCesUtf32To*of seven encodings on surrogates, C1 controls and a one-byte target. The single-character forms here now answer as the console does:0x805C0015, not0x805C0014; a value past U+10FFFF stays0x805C0014;DST_BUFFER_ENDstores the length the character needs (2 for U+3042 into a one-byte target), and any other refusal stores a zero length;Ucs2To*andUtf32To*, which share the helper, so their tests changed with it.The table differences the sweep found (CP932 forms, C1 and others) are other PRs' topics: #10186 measured the EUC-JP and Shift-JIS encoders, and the Shift-JIS U+0080-U+009F answer
0x805C0024is in it, so it is not repeated here.Tested
12e3082520merged ontomain25c1aa1e79: the 14guest_ces*tests pass on two runs; withmain'sExport.cpp,PendingExports.cppandApi.hppthe tests no longer build.Ubuntu 24.04 x86-64 in a Docker container under Rosetta on an Apple M5 Mac, GCC 13.3, Release:
All 14
guest_ces*tests pass.guest_ces_mbcandguest_ces_mbc_moduletake 0.27 s each. I extended #8993'sGuestCesMbc.cpp, which is already registered in CMake, so that it checks:sceCesMbcToUtf32, the rest answerUNASSIGNED_CODE, and U+10000, U+1F600 and U+10FFFF answerUNASSIGNED_CODEin the 7 forms that can carry them;sceCesMbcTo*output into the matching*ToMbc. For every profile, the number of cells that come back byte for byte equals the number of mapped code points: 256 for each single-byte profile, 7,517 for CP932, 13,303 for CP51932, 7,606 for EUC-CN, 21,920 for GBK, 8,354 for EUC-KR, 17,176 for UHC and 13,621 for Big5. The UHC, EUC-KR and GBK counts match Python'scp949andgbkcodecs (GBK plus the0x80euro);82 A0in CP932, U+4E02 to8F B0 A1in CP51932 and81 40in GBK but unassigned in EUC-CN, U+AC02 to81 41in UHC but unassigned in EUC-KR, U+4E00 toA4 40in Big5);C0 80,E0 80 80,F0 80 80 80and others), encoded surrogates, values above U+10FFFF, bad leads and continuations, cut sequences, lone and reversed UTF-16 surrogates in all three byte orders, and UCS-2/UTF-32 surrogates,0x110000and0xFFFFFFFF;beand are rejected throughle), null length pointers, and that the output buffer is untouched after every failure. The length outputs follow the console (next section): untouched after an argument error and in the UTF-8 and UTF-16 buffer forms, zero after a refused character and the needed length afterDST_BUFFER_ENDin the single-character forms.Negative control: with the base
Export.cpprestored, the test no longer links because the stubs are gone (undefined reference to sceCesUtf32ToMbcand the other 7). With the basePendingExports.cpprestored as well,guest_ces_mbcandguest_ces_mbc_moduleabort withsceCesUcs2ToMbc not implementedand the other 12 tests still pass. After restoring both files all 14 pass again.python3 tools/progress.py --module libSceCesCs: 217/287 before, 225/287 after.python3 tools/check_conventions.py --base 15e71dbe11passes. Not tested on a console, on Windows or with a title. I didn't runtools/pr_overlap.py; I checked the open libSceCesCs PRs by hand instead.Hosted runs on my fork (GitHub runners), this branch
524c49e8cand its basec020ce893:net_dontwait_blocking_*tests fail on both.8ccc8df491(verify run on my fork; Ubuntu 24.04, GCC, Release, lavapipe): everyguest_ces*test passes; its one failure,agc_driver_sgpr_pattern_fill_keys, ismain's on that runner. macOS (Apple clang 21, x86-64): all sevenguest_ces*sources pass against thisExport.cpp.guest_ces*tests pass (14/14; 14/14 on the base).Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)