Skip to content

ci: Windows check for libc sscanf rebase - #20

Closed
KernelPanicNT wants to merge 268 commits into
mainfrom
feat/libc-sscanf-guest-wide-conversions
Closed

KernelPanicNT wants to merge 268 commits into
mainfrom
feat/libc-sscanf-guest-wide-conversions

Conversation

@KernelPanicNT

Copy link
Copy Markdown
Owner

Temporary draft to run the Windows build of the rebased branch; it will be closed after the run.

fogydes and others added 30 commits October 14, 2026 11:14
…rate outside 0..2

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… invalid directory name

An unterminated or empty directory name, "." or "..", or a name
containing "/", "\" or ":" now returns SAVE_DATA_ERROR_PARAMETER and
leaves the mount result unchanged. The SDK 12.000 reference lists that
code for an invalid parameter of sceSaveDataMount3, KytyPS5's
SaveDataMount3 returns it for an invalid name, and sceSaveDataDelete
and sceSaveDataConvert already return it here for the same check.
It threw before, which stopped Minecraft Preview (PPSA19639) on
entering a world.

The Mount3 trace now prints at most the 32 bytes of the directory name
and the 16 bytes of the mount point, since both can be unterminated
when the mount fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Guest threads run on host stacks that Windows reserves (0x210000 bytes
by default) and commits on demand. Resident Evil Village protects one
thread's whole host stack with 0xc2 at startup while its lowest 0xd000
bytes are still only reserved, so the Windows mprotect emulation threw.
When such a stack sat inside the arena bounds as a host region, the call
took the arena commit path and failed to split a placeholder that was
never one.

Commit the reserved pages of a host range before protecting it, and only
use the arena commit for ranges the arena owns.
pr-intake runs once per opened PR, and each run lists every open PR by
the author. When an author opens several PRs within seconds, every run
sees all of them and closes its own, so a newcomer opening two PRs at
once loses both, and an author with one merge opening 21 loses all 21.
On opened events the limit now counts only lower-numbered PRs, so the
earliest ones stay open and only the PRs over the limit are closed.
Reopened events still count every open PR, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zyXkUzTZGh3nBwNMtrLaW
Stale conflicts runs actions/stale with only-pr-labels: needs rebase.
actions/stale skips any PR without all only-labels before it looks at
remove-pr-stale-when-updated, so after a rebase removes needs rebase the
PR is never processed again and keeps its stale label for good. A step
before actions/stale now removes stale from open PRs that no longer
carry needs rebase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zyXkUzTZGh3nBwNMtrLaW
AllocateHostStack passes MAP_STACK to mmap. The macOS SDK defines
MAP_NORESERVE but not MAP_STACK, so Export.cpp does not compile there.
Build the flags in a local variable and add MAP_STACK only where the
host defines it. Linux keeps the same flags.
Ninja Multi-Config writes one add_test per configuration and a final NOT_AVAILABLE one for the same name. The audit kept only the last, so every test executable was reported as never run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he region that holds it

Since the cached address space keeps a read-only V# that only partly
overlaps its base regions (readsOverBase), a build's own regions can
overlap base regions. UploadPrepare merges overlapping own views, so a
merged region can begin before the base region that holds a view's first
byte. owner() still took whichever candidate began later, so Descriptor
bound such a view through one base region it does not fit:

  guest buffer view 0x1f0494592c+0x1b2190 exceeds its GPU owner
  0x1f04940000-0x1f04950000 (buffer 0, direct 1, mirror 0)

owner() now takes the range's end and prefers the candidate that holds
the whole range. When both or neither do, it keeps the previous rule.
Every caller already knew the end it passes.
With every queue idle, no completions pending and no storage results
pending, queue 0 took the idle branch, found nothing to store
(idleResultsPending() is false since boykopovar#4410 added the AnyPending() check)
and re-checked at once: the condition kept for "nothing was stored"
continued the loop whenever storeIdleResults was false. Queue 0 never
reached its wait and spun on the driver mutex, a full host core for as
long as the GPU sat idle.

Queue 0 now re-checks only when storage results became pending since the
check or a queue finished work (idle epoch changed); otherwise it waits
for a submission or the next idle epoch as before.

Test: agc_driver_queue_zero_idle_wait submits a NOP on queue 0 and
requires queue 0 to go dormant with nothing pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The area-labels workflow listed open PRs with -L 200, so with more than 200
open PRs the older ones never entered the todo list and never got their area
labels (boykopovar#3295 changes libkernel and has no libkernel label). List up to 1000;
the head -n 40 cap still bounds labeler work per run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zyXkUzTZGh3nBwNMtrLaW
DecodeInstruction returned before reading the ModRM of FF /3 and FF /5,
so a far CALL or JMP through a RIP-relative pointer had no RIP-relative
displacement. A stub that moved such a JMP copied the displacement
without relocating it.

The decoder was compared with iced-x86 (AMD decoding) over 3.99 million
encodings: every opcode of the legacy, 0F, 0F38 and 0F3A maps under 34
prefix combinations and the VEX 0F, 0F38 and 0F3A maps, each with 48
ModRM forms. Apart from this, it agrees on length, RIP-relative offset,
control flow kind and branch target for every valid Zen 2 instruction
except near branches with a 66 prefix, recorded as technical debt, and
kernel-only returns, which it treats as sequential.

Add the comparison's metadata as cases: one RIP-relative encoding per
opcode, map and immediate size, every FF /r form, and the branch forms
with their flow kind and target. The existing cases check lengths only;
a loop or jrcxz decoded as an unconditional jump passed the whole suite.
… array

A shader with any v_movreld kept its whole relative-addressing window (167
registers in a PPSA08427 compute shader) in one Function-storage array, which
the device puts in local memory. The window array now holds only the slots the
relative accesses likely reach (from a bound analysis of their indices); every
other slot is a variable of its own the device can keep in a register. A
relative access whose index lands past the array at run time switches over
those variables, so the guess only affects speed. APS5_NO_WINDOW_NARROWING=1
turns it off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uzy15wqYTt6iWyxYXEzUWo
…s after UploadPrepare

UploadFinish dissolves the cached address space when an import was
retired after the space was built. The space's base regions are then
merged with the build's own regions, which since readsOverBase may
overlap them. owner() searched the merged list for the region with the
greatest begin, a base region of one mapping, so a read-only V# merged
into an own region that began earlier was bound through it again:

  guest buffer view 0x1f0390c1c4+0x10c1cc exceeds its GPU owner
  0x1f03900000-0x1f03910000 (buffer 0, direct 1, mirror 0)

The dissolve now notes when the merged list overlaps, and owner() then
looks back for a region that holds the whole range. The test's third
build retires the imports between UploadPrepare and UploadFinish.
Each SharedRange in agc_host_import_sparse registered a pointer to its
Backing in the global list Resolve searches, and never removed it. The
ranges live on the stack of each check, so by the last check the list
held pointers into stack frames that had been reused. On this machine
Resolve matched one of them for the fourth check's range and returned
an unrelated descriptor (st_size 0, offset 46330441829925), the sparse
path was not chosen, and the check failed with "a failure at
vkQueueBindSparse after the sparse path was chosen did not throw".
Whether it passes depends on what the compiler leaves in those frames.

The range now removes its Backing when it is destroyed. The test passes
20 of 20 here, and fails again when a vkQueueBindSparse failure no
longer throws, which it could not show before.
The Rosetta split covered only VEX scalar compares. boykopovar#5642 measured the
same lost load after legacy CMPSS and CMPSD, and the decoder already
hands them to the matcher with the right length and RIP offset.

Recognise F3 or F2, segment overrides and an optional REX before
0F C2 /r ib, with the same predicate rule as the VEX forms. A 66, 67 or
LOCK prefix, or both F2 and F3, keeps the instruction inline as before.
CONTRIBUTING.md says unimplemented exports call
NotImplemented_nid_no_patch(__func__), and 362 calls in core/ do. A stub
generated for a NID with a known name passed the NID string instead,
so its log line showed tNn5WBkta60 rather than sceAmprCommandBufferNop
and the output had to be edited by hand. Named stubs now use __func__;
stubs with an unknown name keep the NID, the only identifier they have.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zyXkUzTZGh3nBwNMtrLaW
On Windows, piped or redirected output uses the ANSI code page, so a
trace whose thread or slice names are not in cp1252 (a Japanese thread
name, for example) made the markdown digest stop with
UnicodeEncodeError after the work was done. stdout is now set to UTF-8
when the tool runs from the command line, as check_conventions.py does.
The --json output was not affected because json.dumps escapes non-ASCII.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zyXkUzTZGh3nBwNMtrLaW
…itles pass

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guest formatter passed the flags of %o, %u, %x and %X to the host, and
MinGW's printf prefixes a space to %u when the space flag is set: "% u" of 5
gave " 5". C17 7.21.6.1 applies both flags to signed conversions only, and
FreeBSD 11.4 vfprintf clears the sign for every unsigned conversion (nosign).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adriadam10 and others added 27 commits October 15, 2026 22:58
…niso-minmax-reduction

fix(agc): accept a min or max reduction sampler with anisotropic filtering
feat(libc): provide the runtime scripting allocator hooks
…der-discard-3298

fix(agc): discard recorder batches after submission failure
…e-exit

fix(libc): skip guest exit handlers on host window close
…-name-interpolant-mapping-10000

refactor(agc): name dbOlWdppb4o and vieBRwlh1Lw the _10000 interpolant mappings
…rough-2d-array

fix(shader): read explicit-LOD and level-zero 2D-array samples through 1D T#s as measured
…ialog-native-state-checks

fix(libSceSaveDataDialog.native): validate dialog state in close, get result and terminate
…default-cx-state-flat

feat(libSceAgc): implement sceAgcGetDefaultCxStateFlat
…warning

fix(avplayer): defer loop warnings until frame delivery
…flags

feat(libkernel): implement kevent EV_DISABLE, EV_DISPATCH and EV_FORCEONESHOT
…lear-current-main

fix(agc): ignore stale depth clear flags when no planes are bound
…log-coverage

test(libSceLoginDialog): cover uninitialized close and initial status in guest test
…exible-memory-size-zero

fix(kernel): read a zero flexibleMemorySize in param.json as the default budget
…ailure

fix(relinker): propagate POSIX autorun failures
…g-coverage

test(libSceCdlgG2P): cover uninitialized close and initial status in guest test
…dialog-coverage

test(libSceVrSetupDialog): cover uninitialized close and initial status in guest test
…log-unused-header-and-close-test

fix(libScePlayGoDialog): drop unused header and cover uninitialized close in guest test
…ort-window

fix(agc): promote a held import window to its whole allocation
…iew-dialog-error-codes

fix(libSceCdlgPlayerReview): return error codes instead of throwing in initialize and terminate
…rd-duplicate-open-error

fix(libSceIme): return error codes instead of throwing on duplicate open or close
…log-coverage

test(libSceErrorDialog): cover initial status queries and uninitialized close in guest test
…tor-io-lock

fix(libkernel): serialize Windows vectored file transfers
…-mode-and-trinity

test(libkernel): cover sceKernelIsTrinityMode and dual-null in operation mode guest test
…rature-probe-coverage

test(libkernel): cover valid probe in cpu temperature guest test
…target-without-msaa-enable

fix(agc): rasterize a multisampled target without MSAA_ENABLE at the pixel center
perf(agc): load the pipeline cache file only on the windowed device and save without re-reading an unchanged file
On Linux, sscanf, vsscanf, sscanf_s and vsscanf_s threw for %ls, %lc,
%l[, %S and %C because glibc stores a 32-bit wchar_t per character into
the guest's 16-bit buffer. A format with one of these conversions is now
scanned directive by directive in ScanGuest: each wide directive reads
its bytes as the narrow directive does and widens every byte through
this library's mbrtowc, which is what FreeBSD 11.4's vfscanf.c reads in
the single-byte C locale of none.c. The byte buffer for a wide directive
is bounded by the remaining input, not only by the guest's width.

As in FreeBSD, %S and %C are wide whatever length modifier precedes
them. The format pre-scan and ScanGuest recognise the q length modifier
as FreeBSD does, so %lS, %hC and %qS are found too instead of reaching
glibc, and %qd or %qn in a format scanned by ScanGuest stores a long
long. On Windows, ScanGuest hands q to the host as ll for integer
conversions. A narrow s, c or [ is handed to the host without any length
modifier other than l, so %lls, %qs or %Lc in a format scanned by
ScanGuest are narrow, as in FreeBSD, instead of reaching glibc as wide.

A wide conversion combined with a positional argument or the ' flag
still throws. fscanf keeps throwing for wide conversions.

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

Copy link
Copy Markdown

Progress report (b08db6a → 29cfd99)

📈 System libraries: 88.86% (+0.16%, +23 implemented, -2 removed functions)

✅ 23 implemented
Library Name
libSceAgc sceAgcCreateInterpolantMapping_10000
libSceAgc sceAgcGetDefaultCxStateFlat
libSceAgc sceAgcUpdateInterpolantMapping_10000
libSceNpManager sceNpGetUserIdByAccountId
libc WideCollateCompare
libc WideCollateHash
libc WideCollateTransform
libc _ZNSt7collateIwE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix
libc __isfinitel_nid_postfix
libc fgetws_nid_postfix
libc getchar_unlocked_nid_postfix
libc getwc_nid_postfix
libc getwchar_nid_postfix
libc putchar_unlocked_nid_postfix
libc putwc_nid_postfix
libc putwchar_nid_postfix
libc scriptingFreeMem_nid_postfix
libc scriptingGetMem_nid_postfix
libc vsscanf_nid_postfix
libkernel munlockall_nid_postfix
libkernel pthread_mutexattr_getpshared_nid_postfix
libkernel pthread_mutexattr_setpshared_nid_postfix
libkernel sceKernelMunlockall_nid_postfix
🗑️ 2 removed
Library Name
libSceAgc sceAgcUnknownCreateInterpolantMapping
libSceAgc sceAgcUnknown_vieBRwlh1Lw

@KernelPanicNT

Copy link
Copy Markdown
Owner Author

Windows run 38867947343 passed; the branch is now upstream as boykopovar#6731.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.