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>
32 KiB
Xenia-Canary Boot State — Comprehensive Inventory Immediately Before Guest XEX EntryPoint
Context
This document is a research deliverable: a precise, source-verified inventory of every observable subsystem state that the guest XEX sees at the moment its EntryPoint is about to receive control. Driving motivation is RE on Project Sylpheed, where divergence vs. real hardware (or vs. canary) at boot can mask the actual root cause of a wedge. Existing notes/memory may be wrong; this report is built bottom-up from current source in xenia-canary/.
All citations are markdown links into the repo. Where an agent claim was wrong it has been corrected and called out.
0. The Boot Sequence (one-screen overview)
The order in which xenia reaches the guest entrypoint, from src/xenia/emulator.cc:280-360:
Emulator::Initializeconstructsgraphics_system_(factory). emulator.cc:283InputSystemcreated +Setup(). emulator.cc:295-307VirtualFileSystemcreated. emulator.cc:317KernelStatecreated (this runsInitializeKernelGuestGlobals()from its ctor, kernel_state.h:68).- HLE kernel modules loaded in order:
XboxkrnlModule,XamModule,XbdmModule. emulator.cc:327-329 — each ctor allocates guest-visible export variables. graphics_system_->Setup(...)— register file, gamma ramps, MMIO range, presenter, CP thread. emulator.cc:336-339audio_system_->Setup(...)— XMA decoder, worker thread parked. emulator.cc:347ExceptionHandler::Install. emulator.cc:358- (later, on title launch)
Emulator::LaunchTitlebuilds the VFS device + symlinks, callsKernelState::LaunchModulewhich callsSetExecutableModule(which spawns the kernel dispatch worker) and thenXThread::Createfor the main thread withX_CREATE_SUSPENDED. kernel_state.cc:403-430 processor()->PreLaunch()(optional debugger wait). kernel_state.cc:427- Main thread is resumed → host thread lambda runs
Execute()→ backend dispatches to PC =entry_point_. xthread.cc:421-445, 469-471
Steps 1–8 occur once per emulator instance. Steps 9–11 occur once per title and are the immediate prelude to the guest's first PPC instruction. Everything below describes the state at the boundary between step 11 and the first guest insn.
1. PPC CPU State (entry thread)
All values from src/xenia/cpu/thread_state.cc:66-112, unless otherwise noted.
1.1 GPRs
| Reg | Value | Source |
|---|---|---|
| r0 | 0 (memset) | thread_state.cc:84 |
| r1 (SP) | stack_base (top of stack, see §2) |
thread_state.cc:95 |
| r2 | 0x20000000 (constant — comment: "used by hv only i think") |
thread_state.cc:98 |
| r3 | start_context argument; for the main thread this is 0 (LaunchModule passes 0 as start_context, see kernel_state.cc:414) |
[processor.cc Execute() arg setup] |
| r4..r12 | 0 (memset) | — |
| r13 | pcr_address — host pointer into KPCR (see §1.3 / §3.4) |
thread_state.cc:100 |
| r14..r31 | 0 (memset) | — |
Note that the XEX ABI does NOT receive its entry args in r3 for the main thread: the main thread invokes the XEX directly with start_context = 0. Worker / kernel threads created via ExCreateThread go through xapi_thread_startup and pass start_context in r3.
1.2 Special-purpose registers
| SPR | Value | Note |
|---|---|---|
| LR | 0 | (memset) |
| CTR | 0 | (memset) |
| MSR | 0x9030 |
Quoted comment: "dumped from a real 360, 0x8000" — thread_state.cc:104 |
| XER (ca/ov/so) | 0 | Split fields, all zeroed |
| FPSCR | 0 | (memset; no explicit rounding-mode setup — default is RN=00 round-to-nearest) |
| CR0..CR7 | 0 | (memset) |
| VSCR | 0x00010000 (NJ bit = 1, Non-Java IEEE mode) |
thread_state.cc:103 — Correction: Agent #1's claim of 0x00010016 was wrong; actual constant is vec128i(0,0,0,0x00010000) |
| VRSAVE | 0xFFFFFFFF |
thread_state.cc:111 — "closer to correct than 0" |
| DEC, TBL/TBU | 0 (memset) | — |
| PC | entry_point_ extracted from XEX |
user_module.cc:230, passed via kernel_state.cc:415 |
1.3 FPRs, VMX/VR
- All 32 FPRs zeroed by memset of
PPCContext(thread_state.cc:84). - All 128 vector registers (VMX128) zeroed by the same memset.
vrsave = 0xFFFFFFFFis the only non-zero vector-related slot.
1.4 Host-side stash bound to the context
Beyond architectural state, the PPCContext carries pointers used by JIT-generated code and trampolines (thread_state.cc:87-92):
context->global_mutex=&xe::global_critical_region::mutex()context->virtual_membase/physical_membasecontext->processor/thread_state/thread_id- (set later by
XThread::Create)context->kernel_state— xthread.cc:393
The context buffer itself is guest-VA-aligned so its low 32 bits end in 0xE0000000 — clever trick at thread_state.cc:26-56 gives the backend room to use int8 displacements into a preceding granule for backend-specific data.
2. Memory Layout & Heaps
2.1 Guest VA partitioning
The 2 GiB guest VA is shared across heaps managed by Memory (src/xenia/memory.cc, memory.h). Notable named ranges:
- Default user VA heap for small / large allocations.
- Stack range
0x70000000 – 0x7F000000— hardcoded constantskStackAddressRangeBegin/kStackAddressRangeEndat xthread.h:362-363. - Physical mirrors at the A0/C0/E0 high-VA aliases of physical memory (multiple VA views of the same backing pages — required for GPU/audio DMA semantics).
- System heap — kernel-side allocator backing the
SystemHeapAlloccalls used byXboxkrnlModule,XamModule,KernelState, and per-thread bookkeeping. Backs PCR, TLS, KTHREAD, kernel guest globals, kernel exports listed in §3. - Reserved high range for kernel objects / object table.
2.2 Stack (boot thread)
Per xthread.cc:275-301:
- Requested size from XEX
XEX_HEADER_DEFAULT_STACK_SIZE(rounded up to heap page size, default 4 KiB or 64 KiB depending on XEX page-size flag). - Allocated as
actual_size = size + 2*page_size(one guard page top, one bottom). - Guard pages set to
kMemoryProtectNoAccess. Body is RW. stack_limit_ = base + page_size(low water),stack_base_ = stack_limit_ + size(high water; this is what r1 is set to).
2.3 TLS block
Per xthread.cc:327-361:
- Slots from
xex2_opt_tls_info.slot_countif present, else 1024 (kDefaultTlsSlotCountxthread.cc:335). - Layout:
[extended TLS image | slot_count*4 bytes of slots].tls_static_address_= base,tls_dynamic_address_ = base + extended_size. - Initial state: zeroed via
Memory::Fill, then game-provided TLS image copied fromraw_data_addressif non-zero. - Accessed at guest runtime through
r13 + 0(KPCR'stls_ptrfield).
2.4 KPCR (Processor Control Region) — what r13 actually points at
Per xthread.cc:379, 401-411: 0x2D8 bytes allocated from system heap; the fields set before entry are:
| Offset | Field | Value at entry |
|---|---|---|
| 0x000 | tls_ptr |
tls_static_address_ |
| 0x030 | pcr_ptr |
self (pcr_address_) |
| 0x038 | host_stash |
(uint64_t)thread_state_->context() (host pointer punned into u64) |
| 0x070 | stack_base_ptr |
stack_base_ |
| 0x074 | stack_end_ptr |
stack_limit_ |
| 0x100 | prcb_data.current_thread |
guest KTHREAD object guest VA |
| 0x104 | prcb |
pcr_address + offsetof(X_KPCR, prcb_data) |
prcb_data.dpc_active |
0 |
Everything else in the KPCR is zero at entry.
2.5 XEX image & sections
Loaded by XexModule (src/xenia/cpu/xex_module.cc plus src/xenia/kernel/user_module.cc):
- Header copied into the system heap, accessible as
guest_xex_header_(user_module.cc:224). - Entry point + stack/tls/workspace sizes pulled via
GetOptHeader(user_module.cc:230-234). - PE sections mapped at their declared VAs with section flags;
.textis X+R (or X+R+W ifwritable_code_segmentscvar set). - Import tables resolved during
LoadContinue— each import slot is patched to invoke the host kernel export trampoline directly (no guest thunk). - Title workspace heap created at the XEX-declared address if
XEX_HEADER_TITLE_WORKSPACE_SIZEis set (user_module.cc:237).
3. Kernel / xboxkrnl Guest-Visible State
Verified directly against src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc and src/xenia/kernel/kernel_state.cc.
3.1 Pre-initialized exported variables (xboxkrnl.exe)
Created at XboxkrnlModule ctor — these are visible before entry because the ctor runs at step 5 of §0.
| Export | Size | Initial bytes | Source |
|---|---|---|---|
| KeDebugMonitorData | 4 (or 4+sizeof(X_KEDEBUGMONITORDATA) if cvar on) | 0 (off path); points to struct w/ callback fn ptr (on path) |
xboxkrnl_module.cc:80-102 |
| KeCertMonitorData | same | 0 / struct + callback |
xboxkrnl_module.cc:104-123 |
| XboxHardwareInfo | 16 | [0]=0x20 (HDD bit), [4]=0x06 (CPU count), rest 0 |
xboxkrnl_module.cc:136-141 |
| ExConsoleGameRegion | 4 | 0xFFFFFFFF |
xboxkrnl_module.cc:146-150 |
| XexExecutableModuleHandle | 4 | uninit at ctor; populated later when SetExecutableModule runs |
xboxkrnl_module.cc:161-164 |
| ExLoadedImageName | kExLoadedImageNameSize (1024-aligned) |
uninit at ctor; filled later with module path | xboxkrnl_module.cc:171-174 |
| ExLoadedCommandLine | aligned(strlen+1, 1024) | "default.xex" + optional cvars::cl, NUL-padded |
xboxkrnl_module.cc:181-194 |
| XboxKrnlVersion | 8 | kernel_state_->GetKernelVersion() (verify exact bytes in kernel_state.h) |
xboxkrnl_module.cc:199-204 |
| KeTimeStampBundle | 24 | populated lazily on first read via GetKeTimestampBundle() — see §3.2 |
xboxkrnl_module.cc:206-208 |
| ExThreadObjectType, ExEventObjectType, ExMutantObjectType, ExSemaphoreObjectType, ExTimerObjectType, IoCompletionObjectType, IoDeviceObjectType, IoFileObjectType, ObDirectoryObjectType, ObSymbolicLinkObjectType, UsbdBootEnumerationDoneEvent | each → offset within KernelGuestGlobals block |
populated by InitializeKernelGuestGlobals() (§3.3) |
xboxkrnl_module.cc:214-225 |
Correction vs Agent #3: KeTimeStampBundle initialization does NOT happen in
xboxkrnl_module.cc; it lives inKernelState::CreateKeTimestampBundleat kernel_state.cc:1272-1295 and is created lazily on first call toGetKeTimestampBundle(). AHighResolutionTimer::CreateRepeatingis then armed to callUpdateKeTimestampBundle()periodically.
3.2 KeTimeStampBundle layout (X_TIME_STAMP_BUNDLE)
Initialized in kernel_state.cc:1272-1295:
| Offset | Field | Initial value |
|---|---|---|
| +0x00 | interrupt_time (u64) |
current interrupt-time value |
| +0x08 | system_time (u64) |
current system time |
| +0x10 | tick_count (u32) |
Clock::QueryGuestUptimeMillis() |
| +0x14 | padding (u32) |
0 |
A repeating HighResolutionTimer updates these fields every tick (kernel_state.cc:1292-1294).
3.3 KernelGuestGlobals — the big preinitialized blob
Allocated and zeroed at kernel_state.cc:1511-1516; see the KernelGuestGlobals struct definition at kernel_state.h:115-.... Fields include:
ExThreadObjectType,ExEventObjectType,ExMutantObjectType,ExSemaphoreObjectType,ExTimerObjectType,IoCompletionObjectType,IoDeviceObjectType,IoFileObjectType,ObDirectoryObjectType,ObSymbolicLinkObjectTypeUsbdBootEnumerationDoneEventOddObj(referenced kernel_state.cc:1527)system_process,title_process,idle_process(accessor methods at kernel_state.h:212, 216, 220)
Each guest object type is filled with the kernel's view of how dispatcher headers / object headers look. Bytes at these offsets are observable as dq constants by the guest before entry.
3.4 ProcessInfoBlock
Filled by InitializeProcess (called from SetExecutableModule). Notable preinit fields per Agent #3's report:
- +0x0C:
0x0000007F - +0x10:
0x001F0000 - +0x14:
thread_count = 0 - +0x1B:
0x06 - +0x1C:
kernel_stack_size = 16384 - +0x20:
process_type = X_PROCTYPE_USER(orX_PROCTYPE_TITLEfor title) - +0x24..+0x4F: TLS info copy from XEX header
3.5 Object table
- Empty before
LaunchModule. As soon asSetExecutableModuleruns, the executable module's handle is the first allocation. - The kernel dispatch worker thread handle is the second.
- The main XThread handle is the third. All allocated from
object_table()(xthread.cc:317 viaCreateNative). XObject::kHandleBase = 0xF8000000; handles spaced by 4.
4. XAM State
4.1 User profile
Created in KernelState ctor (kernel_state.cc:52). Single profile preconfigured at src/xenia/kernel/xam/user_profile.cc:
- XUID:
0xB13EBABEBABEBABE(hardcoded) - Gamertag:
"User" - 18 default profile settings (per Agent #3's enumeration — XPROFILE_GAMER_YAXIS_INVERSION=0, XPROFILE_OPTION_CONTROLLER_VIBRATION=3, XPROFILE_GAMERCARD_REGION=0, XPROFILE_GAMERCARD_CRED=0xFA, etc.).
Spot-check note: I did not re-verify each of the 18 settings by direct read; cite by file before depending on any single value.
4.2 App manager / content manager
AppManagerinstantiated,RegisterApps()called from KernelState ctor — registers known XAM apps. No launch data at entry.ContentManagerrooted atemulator_->content_root()(seeEmulatorctor). Title-specific save/DLC mounts are not yet established at entrypoint; they are established lazily.
4.3 Notification listeners
Empty list at entry (kernel_state.h:219). On first listener registration with mask bit 1 set, the system synthesizes startup notifications (XN_SYS_UI, XN_SYS_SIGNINCHANGED, XN_SYS_INPUTDEVICESCHANGED, XN_SYS_INPUTDEVICECONFIGCHANGED — kernel_state.cc:657-671).
5. Filesystem State
5.1 Devices mounted at entrypoint
In Emulator::LaunchTitle / Emulator::CreateVfsDevice (emulator.cc:376-...):
| Game source | Device(s) registered | Symlinks |
|---|---|---|
.xex (loose folder) |
HostPathDevice(\Device\Harddisk0\Partition1, parent_dir, read_only=!allow_game_relative_writes) |
game:, d: → same |
.iso (XISO) |
DiscImageDevice(\Device\Cdrom0, path) |
game:, d: → same |
| LIVE/CON/PIRS (STFS) | XContentContainerDevice::CreateContentDevice(...) |
game:, d: → same |
| ZAR | DiscZarchiveDevice(...) |
same |
Plus optional mounts driven by cvars (from xenia_main.cc):
mount_scratch→\SCRATCH, symlinkscratch:mount_cache→\CACHE0,\CACHE1,\CACHEwithcache0:,cache1:,cache:
No files are open at entry; the guest opens what it needs.
5.2 Cache & temp
- No CACHE partition data is fabricated. If
mount_cacheis on, host directoriescache/,cache0/,cache1/back the partitions; otherwise they don't exist for the guest at all. - No
STFScontent packages are pre-mounted unless the title was launched from an STFS package.
6. GPU State (Xenos / Vulkan or D3D12 backend)
6.1 RegisterFile
Allocated as host memory in GraphicsSystem ctor at src/xenia/gpu/graphics_system.cc:79-81:
register_file_ = reinterpret_cast<RegisterFile*>(memory::AllocFixed(
nullptr, sizeof(RegisterFile), kReserveCommit, kReadWrite));
This zero-fills the entire register file. No registers are preloaded with non-zero values before entry. XE_GPU_REG_D1MODE_V_COUNTER is later incremented asynchronously by the frame-limiter thread once that thread starts (graphics_system.cc:~177).
6.2 Gamma ramps (the one notable pre-initialized GPU data)
In CommandProcessor::Initialize at src/xenia/gpu/command_processor.cc:130-148: a 256-entry sRGB-table-like ramp (i * 0x3FF / 0xFF) per channel and a 128-entry PWL ramp with delta 0x200 are loaded. These are observable if guest code reads gamma registers before writing them.
6.3 Command Processor / ringbuffer
- The CP thread is spawned in
GraphicsSystem::Setup(graphics_system.cc:135), at step 6 of §0. It blocks onwrite_ptr_index_event_waiting for PM4 work. - The ringbuffer itself is NOT allocated before entry. The guest allocates and registers it via
VdInitializeRingBuffer(xboxkrnl_video.cc:313-319).
6.4 MMIO
The GPU MMIO range [0x7FC80000, 0xFFFF0000] is hooked via Memory::AddVirtualMappedRange from GraphicsSystem::Setup (graphics_system.cc:141-144). Guest reads/writes route to GPU register file handlers.
6.5 Presenter & backend device
- Presenter and the actual Vulkan/D3D12 device + swapchain are created in
GraphicsSystem::Setupwhenwith_presentation=true(graphics_system.cc:116-128). VdInitializeEnginesis stubbed to return 1 — xenia uses no real microcode (xboxkrnl_video.cc:271-280).- EDRAM/tile allocator, surface info, swap counters: not initialized to guest-visible state pre-entry.
6.6 Reported video mode (queried by guest after entry but driven by config)
VdQueryVideoMode at xboxkrnl_video.cc:203-219 reports cvar-driven values: default 1280×720, widescreen=true, is_interlaced=false, refresh_rate=60.0f, video_standard=1 (NTSC), pixel_rate=0x8A, widescreen_flag=0x01. Gamma type=2 (BT.709), power ≈ 2.222.
7. Audio (APU) State
In AudioSystem::Setup (src/xenia/apu/audio_system.cc:48-97) called at step 7 of §0:
queued_frames_clamped to[4, 64]from cvarapu_max_queued_frames(default 8).- 256 client semaphores allocated, initial count 0, max count =
queued_frames_. shutdown_event_,resume_event_created.XmaDecoderinstantiated; itsSetup()runs.- Worker thread spawned, executing
WorkerThreadMain, immediately parked onWaitAny(wait_handles_). No audio is being submitted, no frames queued.
The XMA guest-memory window (typically observed near 0x42500000 per RE notes) has no pre-populated context state — the guest must call XAudioRegisterRenderDriverClient and provide context VAs.
8. HID / Input
InputSystem::Setup (emulator.cc:307) initializes the input layer; per src/xenia/hid/input_system.h:82-85:
connected_slots = bitset<XUserMaxUserCount>(0)— no controller is plugged in at the moment of entry. The driver layer wires up on demand as controllers connect.last_used_slot = 0.Portal(MCP bridge) created.XInputGetCapabilitieson disconnected slots returnsX_ERROR_DEVICE_NOT_CONNECTED(input_system.cc:179).
Vibration state, battery, etc.: nothing reported until a controller is connected.
9. Networking / XNet / Sockets
No network init occurs before entry; the guest must call NetDll_XNetStartup to populate xnet_startup_params (zero-initialized at xam_net.cc:173).
When queried via NetDll_XNetGetTitleXnAddr (xam_net.cc:476-499):
- IP
ina=127.0.0.1(loopback) - Online IP
inaOnline=0.0.0.0 - Online port = 0
- MAC
abEnet=CC CC CC CC CC CC abOnline= 20 zeros- Return code =
XNET_GET_XNADDR_STATIC(0x00000004)
NetDll_XNetGetDebugXnAddr returns XNET_GET_XNADDR_NONE (0x00000001).
No sockets, no system-link, no NIC enumeration at entry.
10. Real-Time Clock & Timebase
Clock::guest_tick_frequency()(src/xenia/base/clock.cc:39) returns the host CPU tick frequency unless overridden byclock_no_scaling. Reported to guest byKeQueryPerformanceFrequency_entry(xboxkrnl_threading.cc:438-443).KeQuerySystemTime_entry(xboxkrnl_threading.cc:483-497) readsClock::QueryGuestSystemTime— wall clock as of emulator startup epoch.KeTimeStampBundle(§3.2) is the cheap shared mailbox; updated by a repeatingHighResolutionTimer.
11. Threading at Entry
At the boundary, the threads that exist are:
- Main XThread (
is_main_thread=true,guest_thread=true) — currently suspended, about to be resumed. Stack range0x70000000-0x7F000000, host stack 16 MiB (xthread.cc:420), priority/affinity set viaGetFakeCpuNumberderived from(creation_flags >> 24)(xthread.cc:395-396). CPU index assigned viaSetActiveCpu(cpu_index)(xthread.cc:464). - Kernel dispatch worker thread — spawned in
SetExecutableModuleto handle guest async callbacks (kernel_state.cc:368-391 ~). Host-side; consumes from a host queue, does not appear in the guest object table. - GPU command processor thread — already running (parked on
write_ptr_index_event_). - Audio worker thread — already running (parked on its semaphore set).
- Optional: frame-limiter thread, presenter thread, KeTimeStampBundle update timer thread.
Worker threads (sub_825070F0-style XAudio/render workers, secondary game workers, XAM threads) do NOT exist yet — they are spawned by guest code post-entry.
Scheduler state:
- No IRQL machinery; guest code runs at PASSIVE-equivalent.
- Quantum / preemption is approximated; ours uses cooperative-ish per-thread quanta.
- DPC list empty (kernel_state.h:233).
12. JIT / Codegen State
- Backend (x64 or AArch64) initialized at
Processorconstruction. backend_->AllocThreadData()andInitializeBackendContext(context_)called fromThreadStatector (thread_state.cc:77, 82).- Code cache empty — entry-point block JITs on first execution unless
enable_early_precompilationcvar pre-compiled it. - Import-table call sites already patched to direct host trampolines (resolved during
XexModule::LoadContinue). - Syscall / MMIO handlers wired up.
13. Misc Peripherals
- DVD / Disc drive: no separate drive state — backed by the VFS device created at title launch. Tray/laser not modeled.
- USB: no enumeration.
UsbdBootEnumerationDoneEventis allocated as a guest event inKernelGuestGlobalsbut its signaled-state at entry is the field default (verify againstKernelGuestGlobalsstruct). - Cache partition: present only if
mount_cachecvar set. - System link / bridged LAN: not initialized.
- Hypervisor surfaces / KdNet / DmEvents: KD/network debug is not implemented.
DebugPrintredirects into xenia's logger. - Emulator-detection signals (intentional or accidental):
KeDebugMonitorDataalways nonzero or known-zero (vs. real-HW behavior), missing/unimplemented kernel exports, exact MSR value0x9030, the constant r2=0x20000000, the fake XUID0xB13EBABEBABEBABE.
14. Single-Page "What is in the registers right now?" Quick Card
For Sylpheed RE workflows where you need to set a breakpoint at the first guest insn:
PC = <XEX entry_point> ; from XEX optional header
r0..r12 = 0
r1 = stack_base (top of 0x70000000–0x7F000000 region, page-aligned)
r2 = 0x20000000
r3 = 0
r13 = pcr_address (KPCR, has tls_ptr at [r13+0])
r14..r31= 0
LR=0 CTR=0 XER=0 CR=0 FPSCR=0
MSR = 0x9030
VSCR = 0x00010000 ; NJ=1
VRSAVE = 0xFFFFFFFF
FPRs = +0.0 (zero bit pattern)
VR0..127= zero
DEC, TB = 0
15. Verification (how to confirm the above for a specific Sylpheed boot)
The deliverable above is a static read of the source. To validate dynamically for a specific run:
- Quick canary smoke test — run xenia-canary against Sylpheed with logging set high enough to catch
XELOGI("XThread{:08X} ({:X}) Stack: {:08X}-{:08X}", ...)from xthread.cc:389. That confirmsstack_base_,stack_limit_,thread_id_. - Drop into JIT entry breakpoint — set a JIT-store probe (per AUDIT-067 pattern in memory) on the guest PC =
entry_point_and dump thePPCContextonce. Compare GPRs/VSCR/MSR against the table above. - Pre-entry kernel-export dump — print the contents of guest VAs for
XboxHardwareInfo,KeDebugMonitorData,KeTimeStampBundle,ExLoadedCommandLineimmediately before resuming the main thread; verify §3.1 expected bytes. - VFS sanity —
KernelState::file_system_->ResolvePath("game:\\default.xex")should succeed;D:should resolve to the same device. - GPU pre-state — assert no PM4 packets have been dispatched (
command_processor_->paused()/ ringbuffer write-ptr == read-ptr) and gamma table contains the linear ramp from §6.2. - Audio pre-state — assert 256 client semaphores all have count=0, worker thread parked, no XMA contexts registered.
- Cross-engine sanity — run xenia-rs against the same XEX with the same cvars; the values that should match between engines: r1/r2/r13/MSR/VSCR/VRSAVE, PC,
XboxHardwareInfo,ExConsoleGameRegion,XexExecutableModuleHandle, the 1024-entry default TLS slot count, stack range, KPCR layout, default profile XUID.
16. Known Unknowns / Things Not Verified in This Pass
- Exact byte contents of
KernelGuestGlobalsobject-type sub-structs (ExThreadObjectTypeetc.) — these are populated inInitializeKernelGuestGlobals(); full byte-level dump would require reading kernel_state.cc:1511 onward in full. XboxKrnlVersionexact 8 bytes — held inKernelVersionstatic, not spot-checked in this pass.- The 18 default profile setting values were taken from Agent #3's report and not individually re-read.
- Exact
xex2_opt_tls_infofields for Sylpheed (slot_count, raw_data_size) — title-specific. - Per-backend (Vulkan vs. D3D12) device-state nuances.
These are noted explicitly so this doc is not mistaken for full coverage.
17. Critical Files Index
For quick navigation:
- src/xenia/cpu/thread_state.cc — PPC context init (canonical truth for GPRs/MSR/VSCR/VRSAVE).
- src/xenia/kernel/xthread.cc — stack, TLS, KPCR, KTHREAD, host-thread creation,
Executedispatch. - src/xenia/kernel/kernel_state.cc — LaunchModule, SetExecutableModule, KernelGuestGlobals, KeTimeStampBundle.
- src/xenia/kernel/kernel_state.h —
KernelGuestGlobalsstruct. - src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc — preinit'd guest-visible kernel-exported variables.
- src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc — Vd* stubs.
- src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc — KeQueryPerformanceFrequency / KeQuerySystemTime.
- src/xenia/kernel/xam/xam_net.cc — XNADDR and network defaults.
- src/xenia/kernel/xam/user_profile.cc — default user profile.
- src/xenia/kernel/user_module.cc — XEX header parsing, entry_point extraction.
- src/xenia/emulator.cc — Initialize/LaunchTitle subsystem order; VFS device factory.
- src/xenia/gpu/graphics_system.cc — GPU setup.
- src/xenia/gpu/command_processor.cc — gamma ramp init, CP thread.
- src/xenia/apu/audio_system.cc — audio worker, client semaphores.
- src/xenia/hid/input_system.h, .cc — controller slots empty at entry.
- src/xenia/memory.cc, .h — heap topology, physical mirrors.
- src/xenia/base/clock.cc — tick frequency, system time.