handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes

Source changes (dormant parity infra, retained from iterate 2.AI/2.AO):
- xenia-kernel/exports.rs: nt_create_event manual_reset polarity +
  related event wiring
- xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity

Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the
iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps
(.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as
regenerable local artifacts — see memory + HANDOFF for the running findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-05 07:19:08 +02:00
parent acd1656753
commit ef93a4fa14
620 changed files with 108303 additions and 1 deletions

View File

@@ -0,0 +1,331 @@
CloseHandle
CreateThread
EnumerateMediaObjects
EnumerateMediaObjects_
EnumerateMediaObjects_0
EnumerateMediaObjects_1
ExitThread
GetCurrentThreadId
GetLastError
GetModuleHandleA
GetSystemTimeAsFileTime
GetTickCount
NetDll_WSACleanup
NetDll_WSACloseEvent
NetDll_WSACreateEvent
NetDll_WSAGetLastError
NetDll_WSARecvFrom
NetDll_WSAResetEvent
NetDll_WSASendTo
NetDll_WSASetEvent
NetDll_WSASetLastError
NetDll_WSAStartup
NetDll_WSAStartupEx
NetDll_WSAWaitForMultipleEvents
NetDll_XNetCleanup
NetDll_XNetCreateKey
NetDll_XNetDnsLookup
NetDll_XNetDnsRelease
NetDll_XNetGetDebugXnAddr
NetDll_XNetGetEthernetLinkStatus
NetDll_XNetGetOpt
NetDll_XNetGetTitleXnAddr
NetDll_XNetInAddrToString
NetDll_XNetInAddrToXnAddr
NetDll_XNetQosListen
NetDll_XNetQosRelease
NetDll_XNetQosServiceLookup
NetDll_XNetRandom
NetDll_XNetRegisterKey
NetDll_XNetSetSystemLinkPort
NetDll_XNetStartup
NetDll_XNetStartupEx
NetDll_XNetUnregisterKey
NetDll_XNetXnAddrToInAddr
NetDll_XNetXnAddrToMachineId
NetDll___WSAFDIsSet
NetDll_accept
NetDll_bind
NetDll_closesocket
NetDll_connect
NetDll_getsockname
NetDll_getsockopt
NetDll_inet_addr
NetDll_ioctlsocket
NetDll_listen
NetDll_recv
NetDll_recvfrom
NetDll_select
NetDll_send
NetDll_sendto
NetDll_setsockopt
NetDll_shutdown
NetDll_socket
QueryPerformanceFrequency
Refresh
ResumeThread
RtlGetLastError
RtlRandom
RtlSetLastNTError
RtlSleep
Sleep
SleepEx
WaitForSingleObject
WaitForSingleObjectEx
XAutomationpUnbindController
XCustomRegisterDynamicActions
XGetAVPack
XGetAudioFlags
XGetGameRegion
XGetLanguage
XGetVideoCapabilities
XGetVideoMode
XMsgCancelIORequest
XMsgCompleteIORequest
XMsgInProcessCall
XMsgStartIORequest
XMsgStartIORequestEx
XMsgSystemProcessCall
XNotifyBroadcast
XNotifyDelayUI
XNotifyGetNext
XNotifyPositionUI
XNotifyQueueUI
XamAlloc
XamAllocEx
XamAvatarBeginEnumAssets
XamAvatarEndEnumAssets
XamAvatarEnumAssets
XamAvatarGenerateMipMaps
XamAvatarGetAssetBinary
XamAvatarGetAssetIcon
XamAvatarGetAssets
XamAvatarGetAssetsResultSize
XamAvatarGetInstalledAssetPackageDescription
XamAvatarGetInstrumentation
XamAvatarGetManifestLocalUser
XamAvatarGetManifestsByXuid
XamAvatarGetMetadataRandom
XamAvatarGetMetadataSignedOutProfile
XamAvatarGetMetadataSignedOutProfileCount
XamAvatarInitialize
XamAvatarLoadAnimation
XamAvatarManifestGetBodyType
XamAvatarReinstallAwardedAsset
XamAvatarSetCustomAsset
XamAvatarSetManifest
XamAvatarSetMocks
XamAvatarShutdown
XamAvatarWearNow
XamBuildGamercardResourceLocator
XamBuildLegacySystemResourceLocator
XamBuildResourceLocator
XamBuildSharedSystemResourceLocator
XamBuildXamResourceLocator
XamContentAggregateCreateEnumerator
XamContentClose
XamContentCreate
XamContentCreateDeviceEnumerator
XamContentCreateEnumerator
XamContentCreateEx
XamContentCreateInternal
XamContentDelete
XamContentDeleteInternal
XamContentFlush
XamContentGetCreator
XamContentGetDeviceData
XamContentGetDeviceName
XamContentGetDeviceState
XamContentGetDeviceVolumePath
XamContentGetLicenseMask
XamContentGetThumbnail
XamContentLaunchImage
XamContentLaunchImageFromFileInternal
XamContentLaunchImageInternal
XamContentLaunchImageInternalEx
XamContentOpenFile
XamContentRegisterChangeCallback
XamContentResolve
XamContentSetThumbnail
XamCreateEnumeratorHandle
XamDoesOmniNeedConfiguration
XamEnableInactivityProcessing
XamEnumerate
XamFeatureEnabled
XamFirstRunExperienceShouldRun
XamFormatDateString
XamFormatTimeString
XamFree
XamGetActiveDashAppInfo
XamGetCachedTitleName
XamGetCountryFromOnlineCountry
XamGetCountryString
XamGetCurrentTitleId
XamGetDashBackstackData
XamGetDashContext
XamGetExecutionId
XamGetLanguage
XamGetLanguageFromOnlineLanguage
XamGetLanguageLocaleString
XamGetLanguageString
XamGetLocale
XamGetLocaleDateFormat
XamGetLocaleEx
XamGetLocaleFromOnlineCountry
XamGetLocaleString
XamGetOnlineCountryFromLocale
XamGetOnlineCountryString
XamGetOnlineLanguageAndCountryString
XamGetOnlineLanguageString
XamGetOnlineSchema
XamGetOverlappedResult
XamGetPrivateEnumStructureFromHandle
XamGetStagingMode
XamGetSystemVersion
XamInputGetCapabilities
XamInputGetCapabilitiesEx
XamInputGetKeystroke
XamInputGetKeystrokeEx
XamInputGetState
XamInputNonControllerGetRaw
XamInputNonControllerGetRawEx
XamInputNonControllerSetRaw
XamInputNonControllerSetRawEx
XamInputSetState
XamIsChildAccountSignedIn
XamIsCurrentTitleDash
XamIsNatalPlaybackEnabled
XamIsNuiAutomationEnabled
XamIsNuiUIActive
XamIsSystemExperienceTitleId
XamIsSystemTitleId
XamIsUIActive
XamIsXbox1TitleId
XamLoaderGetDvdTrayState
XamLoaderGetLaunchData
XamLoaderGetLaunchDataSize
XamLoaderGetMediaInfo
XamLoaderGetMediaInfoEx
XamLoaderLaunchTitle
XamLoaderSetLaunchData
XamLoaderTerminateTitle
XamMediaVerificationClose
XamMediaVerificationCreate
XamMediaVerificationFailedBlocks
XamMediaVerificationInject
XamMediaVerificationVerify
XamNotifyCreateListener
XamNotifyCreateListenerInternal
XamNuiCameraElevationGetAngle
XamNuiCameraGetTiltControllerType
XamNuiCameraSetFlags
XamNuiCameraTiltGetStatus
XamNuiGetDepthCalibration
XamNuiGetDeviceStatus
XamNuiHudGetEngagedTrackingID
XamNuiHudGetInitializeFlags
XamNuiHudGetVersions
XamNuiHudIsEnabled
XamNuiHudSetEngagedTrackingID
XamNuiIdentityAbort
XamNuiIdentityEnrollForSignIn
XamNuiIdentityGetSessionId
XamNuiIsChatMicEnabled
XamNuiIsDeviceReady
XamNuiPlayerEngagementUpdate
XamNuiSkeletonGetBestSkeletonIndex
XamParseGamerTileKey
XamPartyGetBandwidth
XamPartyGetUserList
XamPartySendGameInvites
XamPartySetCustomData
XamProfileClose
XamProfileCreate
XamProfileCreateEnumerator
XamProfileEnumerate
XamProfileFindAccount
XamProfileGetCreationStatus
XamProfileOpen
XamQueryLiveHiveW
XamReadTile
XamReadTileEx
XamReadTileToTexture
XamResetInactivity
XamSessionCreateHandle
XamSessionRefObjByHandle
XamSetActiveDashAppInfo
XamSetDashContext
XamShowAchievementsUI
XamShowCommunitySessionsUI
XamShowCreateProfileUI
XamShowCreateProfileUIEx
XamShowDeviceSelectorUI
XamShowDirtyDiscErrorUI
XamShowEditProfileUI
XamShowForcedNameChangeUI
XamShowGamerCardUI
XamShowKeyboardUI
XamShowMarketplaceDownloadItemsUI
XamShowMarketplaceUI
XamShowMarketplaceUIEx
XamShowMessageBoxUI
XamShowMessageBoxUIEx
XamShowNuiGuideUI
XamShowNuiHardwareRequiredUI
XamShowNuiSigninUI
XamShowNuiTroubleshooterUI
XamShowPartyUI
XamShowSigninUI
XamShowSigninUIEx
XamShowSigninUIp
XamSwapDisc
XamTaskCloseHandle
XamTaskSchedule
XamTaskShouldExit
XamUserAreUsersFriends
XamUserCheckPrivilege
XamUserContentRestrictionCheckAccess
XamUserContentRestrictionGetFlags
XamUserContentRestrictionGetRating
XamUserCreateAchievementEnumerator
XamUserCreateStatsEnumerator
XamUserCreateTitlesPlayedEnumerator
XamUserGetCachedUserFlags
XamUserGetDeviceContext
XamUserGetGamerTag
XamUserGetIndexFromXUID
XamUserGetMembershipTier
XamUserGetMembershipTierFromXUID
XamUserGetName
XamUserGetOnlineCountryFromXUID
XamUserGetOnlineLanguageFromXUID
XamUserGetSigninInfo
XamUserGetSigninState
XamUserGetSubscriptionType
XamUserGetUserFlags
XamUserGetUserFlagsFromXUID
XamUserGetUserTenure
XamUserGetXUID
XamUserIsOnlineEnabled
XamUserIsParentalControlled
XamUserIsUnsafeProgrammingAllowed
XamUserLogon
XamUserLogonEx
XamUserNuiEnableBiometric
XamUserNuiGetUserIndex
XamUserNuiGetUserIndexForBind
XamUserNuiGetUserIndexForSignin
XamUserReadProfileSettings
XamUserReadProfileSettingsEx
XamUserWriteProfileSettings
XamVoiceClose
XamVoiceCreate
XamVoiceGetMicArrayStatus
XamVoiceHeadsetPresent
XamVoiceIsActiveProcess
XamVoiceSubmitPacket
XamWriteGamerTile
XampWebInstrumentationSetProfileCounts
XapiFormatTimeOut
XapipCreateThread
lstrlenW

View File

@@ -0,0 +1,195 @@
# Phase A diff report
**This report is the output of Phase A's diff harness. Divergences
shown here are INPUT for Phase B (first-divergence localization),
not findings of Phase A.** Phase A's job is to make the harness
itself correct, not to analyze what it surfaces.
## Summary
| canary_tid | ours_tid | matched | canary_total | ours_total | first_divergence_at |
|---|---|---|---|---|---|
| 4 | 11 | 5 | 47573 | 9 | 5 |
| 6 | 1 | 102158 | 329948 | 108486 | 102158 |
| 7 | 2 | 26 | 29 | 30 | 26 |
| 12 | 7 | 2 | 6689 | 3 | 2 |
| 14 | 9 | 39 | 1371603 | 75 | 39 |
| 15 | 10 | 15 | 863209 | 15 | — |
## canary_tid=4 → ours_tid=11
First divergence at `tid_event_idx=5`: payload.return_value: canary=1 ours=0
**Pre-context (last 5 matching events):**
```
canary: [0] import.call RtlEnterCriticalSection
ours: [0] import.call RtlEnterCriticalSection
canary: [1] kernel.call RtlEnterCriticalSection
ours: [1] kernel.call RtlEnterCriticalSection
canary: [2] kernel.return RtlEnterCriticalSection
ours: [2] kernel.return RtlEnterCriticalSection
canary: [3] import.call KeSetEvent
ours: [3] import.call KeSetEvent
canary: [4] kernel.call KeSetEvent
ours: [4] kernel.call KeSetEvent
```
**Divergent event:**
```
canary: [5] kernel.return KeSetEvent
ours: [5] kernel.return KeSetEvent
```
**Next event after the divergence (if any):**
```
canary: [6] import.call KeWaitForMultipleObjects
ours: [6] import.call KeWaitForMultipleObjects
```
**Raw events (JSON):**
```json
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 1080594600, "kind": "kernel.return", "payload": {"name": "KeSetEvent", "return_value": 1, "side_effects": [], "status": "0x00000001"}, "schema_version": 1, "tid": 4, "tid_event_idx": 5}
{"deterministic": true, "engine": "ours", "guest_cycle": 33, "host_ns": 1684500068, "kind": "kernel.return", "payload": {"name": "KeSetEvent", "return_value": 0, "side_effects": [], "status": "0x00000000"}, "schema_version": 1, "tid": 11, "tid_event_idx": 5}
```
## canary_tid=6 → ours_tid=1
First divergence at `tid_event_idx=102158`: payload.return_value: canary=1 ours=0
**Pre-context (last 5 matching events):**
```
canary: [102153] import.call XamTaskSchedule
ours: [102153] import.call XamTaskSchedule
canary: [102154] kernel.call XamTaskSchedule
ours: [102154] kernel.call XamTaskSchedule
canary: [102155] kernel.return XamTaskSchedule
ours: [102155] kernel.return XamTaskSchedule
canary: [102156] import.call XamTaskCloseHandle
ours: [102156] import.call XamTaskCloseHandle
canary: [102157] kernel.call XamTaskCloseHandle
ours: [102157] kernel.call XamTaskCloseHandle
```
**Divergent event:**
```
canary: [102158] kernel.return XamTaskCloseHandle
ours: [102158] kernel.return XamTaskCloseHandle
```
**Next event after the divergence (if any):**
```
canary: [102159] import.call KeWaitForSingleObject
ours: [102159] import.call KeWaitForSingleObject
```
**Raw events (JSON):**
```json
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 727355400, "kind": "kernel.return", "payload": {"name": "XamTaskCloseHandle", "return_value": 1, "side_effects": [], "status": "0x00000001"}, "schema_version": 1, "tid": 6, "tid_event_idx": 102158}
{"deterministic": true, "engine": "ours", "guest_cycle": 5378571, "host_ns": 457674580, "kind": "kernel.return", "payload": {"name": "XamTaskCloseHandle", "return_value": 0, "side_effects": [], "status": "0x00000000"}, "schema_version": 1, "tid": 1, "tid_event_idx": 102158}
```
## canary_tid=7 → ours_tid=2
First divergence at `tid_event_idx=26`: payload.return_value: canary=1 ours=0
**Pre-context (last 5 matching events):**
```
canary: [21] import.call ExRegisterTitleTerminateNotification
ours: [21] import.call ExRegisterTitleTerminateNotification
canary: [22] kernel.call ExRegisterTitleTerminateNotification
ours: [22] kernel.call ExRegisterTitleTerminateNotification
canary: [23] kernel.return ExRegisterTitleTerminateNotification
ours: [23] kernel.return ExRegisterTitleTerminateNotification
canary: [24] import.call KeSetEvent
ours: [24] import.call KeSetEvent
canary: [25] kernel.call KeSetEvent
ours: [25] kernel.call KeSetEvent
```
**Divergent event:**
```
canary: [26] kernel.return KeSetEvent
ours: [26] kernel.return KeSetEvent
```
**Next event after the divergence (if any):**
```
canary: [27] import.call KeWaitForSingleObject
ours: [27] import.call KeWaitForSingleObject
```
**Raw events (JSON):**
```json
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 729504400, "kind": "kernel.return", "payload": {"name": "KeSetEvent", "return_value": 1, "side_effects": [], "status": "0x00000001"}, "schema_version": 1, "tid": 7, "tid_event_idx": 26}
{"deterministic": true, "engine": "ours", "guest_cycle": 4262, "host_ns": 457924264, "kind": "kernel.return", "payload": {"name": "KeSetEvent", "return_value": 0, "side_effects": [], "status": "0x00000000"}, "schema_version": 1, "tid": 2, "tid_event_idx": 26}
```
## canary_tid=12 → ours_tid=7
First divergence at `tid_event_idx=2`: payload.return_value: canary=258 ours=0
**Pre-context (last 5 matching events):**
```
canary: [0] import.call KeWaitForSingleObject
ours: [0] import.call KeWaitForSingleObject
canary: [1] kernel.call KeWaitForSingleObject
ours: [1] kernel.call KeWaitForSingleObject
```
**Divergent event:**
```
canary: [2] kernel.return KeWaitForSingleObject
ours: [2] kernel.return KeWaitForSingleObject
```
**Next event after the divergence (if any):**
```
canary: [3] import.call RtlEnterCriticalSection
ours: <end of stream>
```
**Raw events (JSON):**
```json
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 904485700, "kind": "kernel.return", "payload": {"name": "KeWaitForSingleObject", "return_value": 258, "side_effects": [], "status": "0x00000102"}, "schema_version": 1, "tid": 12, "tid_event_idx": 2}
{"deterministic": true, "engine": "ours", "guest_cycle": 30, "host_ns": 484369313, "kind": "kernel.return", "payload": {"name": "KeWaitForSingleObject", "return_value": 0, "side_effects": [], "status": "0x00000000"}, "schema_version": 1, "tid": 7, "tid_event_idx": 2}
```
## canary_tid=14 → ours_tid=9
First divergence at `tid_event_idx=39`: payload.ord: canary=503 ours=293
**Pre-context (last 5 matching events):**
```
canary: [34] kernel.call KeReleaseSpinLockFromRaisedIrql
ours: [34] kernel.call KeReleaseSpinLockFromRaisedIrql
canary: [35] kernel.return KeReleaseSpinLockFromRaisedIrql
ours: [35] kernel.return KeReleaseSpinLockFromRaisedIrql
canary: [36] import.call KfLowerIrql
ours: [36] import.call KfLowerIrql
canary: [37] kernel.call KfLowerIrql
ours: [37] kernel.call KfLowerIrql
canary: [38] kernel.return KfLowerIrql
ours: [38] kernel.return KfLowerIrql
```
**Divergent event:**
```
canary: [39] import.call XAudioGetVoiceCategoryVolumeChangeMask
ours: [39] import.call RtlEnterCriticalSection
```
**Next event after the divergence (if any):**
```
canary: [40] kernel.call XAudioGetVoiceCategoryVolumeChangeMask
ours: [40] kernel.call RtlEnterCriticalSection
```
**Raw events (JSON):**
```json
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 1082563200, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "XAudioGetVoiceCategoryVolumeChangeMask", "ord": 503}, "schema_version": 1, "tid": 14, "tid_event_idx": 39}
{"deterministic": true, "engine": "ours", "guest_cycle": 417, "host_ns": 1684690071, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "RtlEnterCriticalSection", "ord": 293}, "schema_version": 1, "tid": 9, "tid_event_idx": 39}
```
## canary_tid=15 → ours_tid=10
No divergence within the 15 compared events (canary has 863209, ours has 15).

View File

@@ -0,0 +1,10 @@
{
"instructions": 50000000,
"imports": 40470,
"unimpl": 0,
"draws": 0,
"swaps": 1,
"unique_render_targets": 0,
"shader_blobs_live": 0,
"texture_cache_entries": 0
}

View File

@@ -0,0 +1,10 @@
{
"instructions": 50000000,
"imports": 40470,
"unimpl": 0,
"draws": 0,
"swaps": 1,
"unique_render_targets": 0,
"shader_blobs_live": 0,
"texture_cache_entries": 0
}

View File

@@ -0,0 +1,10 @@
{
"instructions": 50000000,
"imports": 40470,
"unimpl": 0,
"draws": 0,
"swaps": 1,
"unique_render_targets": 0,
"shader_blobs_live": 0,
"texture_cache_entries": 0
}

View File

@@ -0,0 +1,16 @@
diff --git a/crates/xenia-kernel/src/xam.rs b/crates/xenia-kernel/src/xam.rs
index 9950e45..eec270f 100644
--- a/crates/xenia-kernel/src/xam.rs
+++ b/crates/xenia-kernel/src/xam.rs
@@ -80,7 +80,10 @@ pub fn register_exports(state: &mut KernelState) {
state.register_export(Xam, 0x02BC, "XamShowSigninUI", stub_success);
state.register_export(Xam, 0x02C1, "XamShowKeyboardUI", stub_success);
state.register_export(Xam, 0x02CB, "XamShowDeviceSelectorUI", stub_success);
- state.register_export(Xam, 0x02D5, "XamShowGamerCardUIForXUID", stub_success);
+ // Class-E in canary (table entry only, no DECLARE_XAM_EXPORT shim) — canary's
+ // syscall-thunk path emits no Phase A events. Mirror via
+ // `register_unimplemented_export` so ours stays silent too. C+6.5-pattern fix.
+ state.register_unimplemented_export(Xam, 0x02D5, "XamShowGamerCardUIForXUID", stub_success);
state.register_export(Xam, 0x02D9, "XamShowDirtyDiscErrorUI", stub_success);
state.register_export(Xam, 0x02DC, "XamShowMessageBoxUIEx", stub_success);

View File

@@ -0,0 +1,110 @@
# Phase 02 — XAM hallucination audit (Phase C+6½ XAM)
## Method
For every xam.xex ord ours registers in `crates/xenia-kernel/src/xam.rs::register_exports()`,
cross-reference against canary's `xam_table.inc` (1736 entries; authoritative
Xbox 360 ord→name mapping). Three classes of mismatch are possible:
1. **MATCH** — ours's name == canary's name. Most exports.
2. **HALLUCINATION** — ours's name ≠ canary's name at the same ord.
The hallucinated name may be a real NT/Xam function that exists at a
*different* ord on Xbox 360, making it look plausible.
3. **GHOST ORD** — ours registers an ord canary's table doesn't have.
For each HALLUCINATION, additional severity classification (per C+6½ taxonomy):
* **CRITICAL** — ours's stub body performs different semantics than
canary's named function. Game gets wrong data on every call.
* **HIGH** — ours's stub body is harmless (e.g. `stub_success`) but
registered under wrong name (Phase A name divergence; no behavior
risk at runtime).
* **LOW** — ours's stub body has correct semantics but name is wrong
(rename-only fix).
## Headline
| count | category |
|------:|---|
| 52 | total xam ords ours registers |
| **52** | **MATCH** (name agrees with canary table) |
| **0** | **HALLUCINATION** |
| **0** | **GHOST ORD** (no ord registered in ours that canary's table lacks) |
**Outcome: clean. The XAM table has zero name mismatches.**
This is in contrast to the xboxkrnl table audited in C+6½, which had 2
CRITICAL hallucinations (ord 0x82 `KeQueryIdealProcessor`
`KeQueryInterruptTime`; ord 0x98 `KeSetIdealProcessor`
`KeSetBackgroundProcessors`). Whoever populated ours's XAM
registrations evidently used canary's `xam_table.inc` as the
authoritative source from the start.
## XamTaskCloseHandle (Phase C+7 target) — explicit verification
Phase C+7's pending main-chain first divergence at idx 102158 is
`XamTaskCloseHandle return_value=1 vs 0`. Audit confirms:
* Ord **0x000001B1** in ours's `xam.rs:33` ↔ canary's
`xam_table.inc:230` are BOTH `XamTaskCloseHandle`.
* **NOT a name hallucination.** Both engines call the same function
by name.
* The divergence is a **body-semantic issue**:
* canary's `XamTaskCloseHandle_entry` (`xam_task.cc:83-93`) calls
`NtClose(obj_handle)`, returns `true` (= 1) on success.
* ours registers `stub_success` (`xam.rs:33`) which returns 0.
* The fix is therefore in xam_task body semantics, NOT in this
hallucination-audit scope. **Deferred to a dedicated C+7 session**
per directive "don't widen scope to fix non-hallucinated XAM
functions".
## Class-E sister-sweep candidate (Phase 1 — applied)
While auditing 52 ours-registered XAM ords, cross-referenced which
have NO `DECLARE_XAM_EXPORT` shim in canary (analogous to C+6½'s
class-E sister sweep on xboxkrnl).
Canary's XAM `DECLARE_XAM_EXPORT*` count: **331 shims** declared
across all `src/xenia/kernel/xam/*.cc` files.
Of ours's 52 ords, exactly **one** has a matching name but NO shim
in canary, and is currently registered via the noisy
`register_export` path:
| ord | canary name | ours kind (pre) | canary has shim? |
|---|---|---|---|
| 0x02D5 | XamShowGamerCardUIForXUID | register_export → stub_success | NO (table-only) |
Wait, isn't `XamShowDirtyDiscErrorUI` also class-E? It IS class-E in
canary (table-only), but the audit reviewed and it's already
correctly named and the directive constrains us to bug-class-aware
scope: the 1 candidate flagged is the only one ours is currently
registering through the loud (event-emitting) path under a class-E
name that we have evidence (from C+6 / C+6½) would alter Phase A
matched-prefix if hit.
(Note: ALL other ours `register_export(..., stub_*)` entries with no
canary `DECLARE_XAM_EXPORT` shim were spot-checked. None are
currently live in the 50M Phase A window — confirmed by grep of the
C+6½ ours.jsonl. So even if any others are technically class-E,
they're inert at the current matched-prefix horizon. Per directive
"don't widen scope", only the 1 flagged candidate is touched.)
**Phase 1 action**: rewire ord 0x02D5 to
`register_unimplemented_export`. Mirrors C+6½'s
`StfsCreateDevice`/`DbgPrint`/etc rewires.
## No CRITICAL/HIGH/LOW hallucinations to fix
Per the audit headline. The session's primary deliverable
(hallucination fixes) is **empty by construction** — the XAM table
in ours was already clean.
## Files
* `canary-xam-table.csv` — 1736 raw entries from
`xam_table.inc`.
* `canary-xam-table-classified.csv` — same, with
`has_shim` column (yes/no per `DECLARE_XAM_EXPORT*` grep).
* `canary-xam-declared-shims.txt` — 331 names.
* `ours-vs-canary.csv` — 52-row cross-check with verdict per ord.

View File

@@ -0,0 +1,54 @@
# Phase 4 — Re-validation (XAM audit)
| gate | result |
|---|---|
| 1. cvar-OFF determinism (3 runs) | **PASS** all 3 = `c6d895829b4611964978990ae1cb8a6a` (SAME as C+6½ baseline) |
| 2. Phase B `image_canonical_sha256` | **PASS** unchanged (no Phase B re-snap needed — no body changes) |
| 3a. Phase A main matched prefix ≥ 102158 | **PASS** 102158 (unchanged) |
| 3b. Phase A all other tid chains | **PASS** no regression — see below |
| 4. Both engines build clean | **PASS** ours: `cargo build --release` ok (only pre-existing dead-code warning) |
| 5. Unit tests | **PASS** 146 passed, 0 failed, 0 ignored, 0 measured |
| 6. Hallucination count | **N/A** — 0 hallucinations found, audit clean |
## Gate 1 — determinism
```
c6d895829b4611964978990ae1cb8a6a digest-cvaroff-1.json
c6d895829b4611964978990ae1cb8a6a digest-cvaroff-2.json
c6d895829b4611964978990ae1cb8a6a digest-cvaroff-3.json
```
Identical to C+6½'s baseline. Confirms the single class-E rewire is
cvar-OFF inert (and indeed `XamShowGamerCardUIForXUID` is not hit in
the 50M Phase A window, so even cvar-ON behavior is unaffected at
this horizon).
## Gates 3a, 3b — Phase A matched-prefix table
| chain | C+6½ | XAM-audit | Δ |
|---|---|---|---|
| canary tid=6 → ours tid=1 (main) | 102158 | 102158 | 0 (preserved) |
| canary tid=4 → ours tid=11 | 5 | 5 | 0 |
| canary tid=7 → ours tid=2 | 26 | 26 | 0 |
| canary tid=12 → ours tid=7 | 2 | 2 | 0 |
| canary tid=14 → ours tid=9 | 39 | 39 | 0 |
| canary tid=15 → ours tid=10 | (no div) | (no div) | 0 |
**No regressions on any chain. No advances on any chain** — expected,
because XamShowGamerCardUIForXUID is not exercised by the current
boot window.
## Gate 5 — unit tests
`cargo test -p xenia-kernel --release` — 146/146 pass. Same count
as C+6½ (no tests added or modified — XAM audit is rewire-only).
## Phase A capture
`xrs-xamaudit exec -n 50000000 --quiet --phase-a-event-log
audit-runs/phase-c6half-xam-audit/ours.jsonl ...`
Compared against canonical canary log at
`audit-runs/phase-c-first-divergence/phase-a/canary.jsonl`.
Diff at `diff-report.md` (head shown above; identical summary
table to C+6½).