# 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/](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](xenia-canary/src/xenia/emulator.cc#L280-L360): 1. `Emulator::Initialize` constructs `graphics_system_` (factory). [emulator.cc:283](xenia-canary/src/xenia/emulator.cc#L283) 2. `InputSystem` created + `Setup()`. [emulator.cc:295-307](xenia-canary/src/xenia/emulator.cc#L295-L307) 3. `VirtualFileSystem` created. [emulator.cc:317](xenia-canary/src/xenia/emulator.cc#L317) 4. `KernelState` created (this runs `InitializeKernelGuestGlobals()` from its ctor, [kernel_state.h:68](xenia-canary/src/xenia/kernel/kernel_state.h#L68)). 5. HLE kernel modules loaded in order: `XboxkrnlModule`, `XamModule`, `XbdmModule`. [emulator.cc:327-329](xenia-canary/src/xenia/emulator.cc#L327-L329) — each ctor allocates guest-visible export variables. 6. `graphics_system_->Setup(...)` — register file, gamma ramps, MMIO range, presenter, CP thread. [emulator.cc:336-339](xenia-canary/src/xenia/emulator.cc#L336-L339) 7. `audio_system_->Setup(...)` — XMA decoder, worker thread parked. [emulator.cc:347](xenia-canary/src/xenia/emulator.cc#L347) 8. `ExceptionHandler::Install`. [emulator.cc:358](xenia-canary/src/xenia/emulator.cc#L358) 9. *(later, on title launch)* `Emulator::LaunchTitle` builds the VFS device + symlinks, calls `KernelState::LaunchModule` which calls `SetExecutableModule` (which spawns the kernel dispatch worker) and then `XThread::Create` for the main thread with `X_CREATE_SUSPENDED`. [kernel_state.cc:403-430](xenia-canary/src/xenia/kernel/kernel_state.cc#L403-L430) 10. `processor()->PreLaunch()` (optional debugger wait). [kernel_state.cc:427](xenia-canary/src/xenia/kernel/kernel_state.cc#L427) 11. Main thread is resumed → host thread lambda runs `Execute()` → backend dispatches to PC = `entry_point_`. [xthread.cc:421-445, 469-471](xenia-canary/src/xenia/kernel/xthread.cc#L421-L471) 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](xenia-canary/src/xenia/cpu/thread_state.cc#L66-L112), unless otherwise noted. ### 1.1 GPRs | Reg | Value | Source | |----|----|----| | r0 | 0 (memset) | [thread_state.cc:84](xenia-canary/src/xenia/cpu/thread_state.cc#L84) | | **r1** (SP) | `stack_base` (top of stack, see §2) | [thread_state.cc:95](xenia-canary/src/xenia/cpu/thread_state.cc#L95) | | **r2** | `0x20000000` (constant — comment: "used by hv only i think") | [thread_state.cc:98](xenia-canary/src/xenia/cpu/thread_state.cc#L98) | | **r3** | `start_context` argument; for the main thread this is `0` (LaunchModule passes 0 as `start_context`, see [kernel_state.cc:414](xenia-canary/src/xenia/kernel/kernel_state.cc#L414)) | [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](xenia-canary/src/xenia/cpu/thread_state.cc#L100) | | 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](xenia-canary/src/xenia/cpu/thread_state.cc#L104) | | 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](xenia-canary/src/xenia/cpu/thread_state.cc#L103) — **Correction: Agent #1's claim of `0x00010016` was wrong; actual constant is `vec128i(0,0,0,0x00010000)`** | | **VRSAVE** | `0xFFFFFFFF` | [thread_state.cc:111](xenia-canary/src/xenia/cpu/thread_state.cc#L111) — "closer to correct than 0" | | DEC, TBL/TBU | 0 (memset) | — | | PC | `entry_point_` extracted from XEX | [user_module.cc:230](xenia-canary/src/xenia/kernel/user_module.cc#L230), passed via [kernel_state.cc:415](xenia-canary/src/xenia/kernel/kernel_state.cc#L415) | ### 1.3 FPRs, VMX/VR - All 32 FPRs zeroed by memset of `PPCContext` ([thread_state.cc:84](xenia-canary/src/xenia/cpu/thread_state.cc#L84)). - All 128 vector registers (VMX128) zeroed by the same memset. - `vrsave = 0xFFFFFFFF` is 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](xenia-canary/src/xenia/cpu/thread_state.cc#L87-L92)): - `context->global_mutex` = `&xe::global_critical_region::mutex()` - `context->virtual_membase` / `physical_membase` - `context->processor` / `thread_state` / `thread_id` - (set later by `XThread::Create`) `context->kernel_state` — [xthread.cc:393](xenia-canary/src/xenia/kernel/xthread.cc#L393) The context buffer itself is *guest-VA-aligned* so its low 32 bits end in `0xE0000000` — clever trick at [thread_state.cc:26-56](xenia-canary/src/xenia/cpu/thread_state.cc#L26-L56) 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](xenia-canary/src/xenia/memory.cc), [memory.h](xenia-canary/src/xenia/memory.h)). Notable named ranges: - **Default user VA heap** for small / large allocations. - **Stack range** `0x70000000 – 0x7F000000` — hardcoded constants `kStackAddressRangeBegin`/`kStackAddressRangeEnd` at [xthread.h:362-363](xenia-canary/src/xenia/kernel/xthread.h#L362-L363). - **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 `SystemHeapAlloc` calls used by `XboxkrnlModule`, `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](xenia-canary/src/xenia/kernel/xthread.cc#L275-L301): - 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](xenia-canary/src/xenia/kernel/xthread.cc#L327-L361): - Slots from `xex2_opt_tls_info.slot_count` if present, else **1024** (`kDefaultTlsSlotCount` [xthread.cc:335](xenia-canary/src/xenia/kernel/xthread.cc#L335)). - 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 from `raw_data_address` if non-zero. - Accessed at guest runtime through `r13 + 0` (KPCR's `tls_ptr` field). ### 2.4 KPCR (Processor Control Region) — what r13 actually points at Per [xthread.cc:379, 401-411](xenia-canary/src/xenia/kernel/xthread.cc#L379-L411): 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](xenia-canary/src/xenia/kernel/user_module.cc#L224)). - Entry point + stack/tls/workspace sizes pulled via `GetOptHeader` ([user_module.cc:230-234](xenia-canary/src/xenia/kernel/user_module.cc#L230-L234)). - PE sections mapped at their declared VAs with section flags; `.text` is X+R (or X+R+W if `writable_code_segments` cvar 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_SIZE` is set ([user_module.cc:237](xenia-canary/src/xenia/kernel/user_module.cc#L237)). --- ## 3. Kernel / xboxkrnl Guest-Visible State Verified directly against [src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc) and [src/xenia/kernel/kernel_state.cc](xenia-canary/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](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L80-L102) | | **KeCertMonitorData** | same | `0` / struct + callback | [xboxkrnl_module.cc:104-123](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L104-L123) | | **XboxHardwareInfo** | 16 | `[0]=0x20` (HDD bit), `[4]=0x06` (CPU count), rest 0 | [xboxkrnl_module.cc:136-141](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L136-L141) | | **ExConsoleGameRegion** | 4 | `0xFFFFFFFF` | [xboxkrnl_module.cc:146-150](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L146-L150) | | **XexExecutableModuleHandle** | 4 | uninit at ctor; populated later when `SetExecutableModule` runs | [xboxkrnl_module.cc:161-164](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L161-L164) | | **ExLoadedImageName** | `kExLoadedImageNameSize` (1024-aligned) | uninit at ctor; filled later with module path | [xboxkrnl_module.cc:171-174](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L171-L174) | | **ExLoadedCommandLine** | aligned(strlen+1, 1024) | `"default.xex"` + optional `cvars::cl`, NUL-padded | [xboxkrnl_module.cc:181-194](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L181-L194) | | **XboxKrnlVersion** | 8 | `kernel_state_->GetKernelVersion()` (verify exact bytes in `kernel_state.h`) | [xboxkrnl_module.cc:199-204](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L199-L204) | | **KeTimeStampBundle** | 24 | populated lazily on first read via `GetKeTimestampBundle()` — see §3.2 | [xboxkrnl_module.cc:206-208](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L206-L208) | | **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](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc#L214-L225) | > **Correction vs Agent #3**: KeTimeStampBundle initialization does NOT happen in `xboxkrnl_module.cc`; it lives in `KernelState::CreateKeTimestampBundle` at [kernel_state.cc:1272-1295](xenia-canary/src/xenia/kernel/kernel_state.cc#L1272-L1295) and is created lazily on first call to `GetKeTimestampBundle()`. A `HighResolutionTimer::CreateRepeating` is then armed to call `UpdateKeTimestampBundle()` periodically. ### 3.2 KeTimeStampBundle layout (`X_TIME_STAMP_BUNDLE`) Initialized in [kernel_state.cc:1272-1295](xenia-canary/src/xenia/kernel/kernel_state.cc#L1272-L1295): | 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](xenia-canary/src/xenia/kernel/kernel_state.cc#L1292-L1294)). ### 3.3 KernelGuestGlobals — the big preinitialized blob Allocated and zeroed at [kernel_state.cc:1511-1516](xenia-canary/src/xenia/kernel/kernel_state.cc#L1511-L1516); see the `KernelGuestGlobals` struct definition at [kernel_state.h:115-...](xenia-canary/src/xenia/kernel/kernel_state.h#L115). Fields include: - `ExThreadObjectType`, `ExEventObjectType`, `ExMutantObjectType`, `ExSemaphoreObjectType`, `ExTimerObjectType`, `IoCompletionObjectType`, `IoDeviceObjectType`, `IoFileObjectType`, `ObDirectoryObjectType`, `ObSymbolicLinkObjectType` - `UsbdBootEnumerationDoneEvent` - `OddObj` (referenced [kernel_state.cc:1527](xenia-canary/src/xenia/kernel/kernel_state.cc#L1527)) - `system_process`, `title_process`, `idle_process` (accessor methods at [kernel_state.h:212, 216, 220](xenia-canary/src/xenia/kernel/kernel_state.h#L212-L220)) 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` (or `X_PROCTYPE_TITLE` for title) - +0x24..+0x4F: TLS info copy from XEX header ### 3.5 Object table - Empty before `LaunchModule`. As soon as `SetExecutableModule` runs, 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](xenia-canary/src/xenia/kernel/xthread.cc#L317) via `CreateNative`). - `XObject::kHandleBase = 0xF8000000`; handles spaced by 4. --- ## 4. XAM State ### 4.1 User profile Created in `KernelState` ctor ([kernel_state.cc:52](xenia-canary/src/xenia/kernel/kernel_state.cc#L52)). 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 - `AppManager` instantiated, `RegisterApps()` called from KernelState ctor — registers known XAM apps. No launch data at entry. - `ContentManager` rooted at `emulator_->content_root()` (see `Emulator` ctor). 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](xenia-canary/src/xenia/kernel/kernel_state.h#L219)). 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](xenia-canary/src/xenia/kernel/kernel_state.cc#L657-L671)). --- ## 5. Filesystem State ### 5.1 Devices mounted at entrypoint In `Emulator::LaunchTitle` / `Emulator::CreateVfsDevice` ([emulator.cc:376-...](xenia-canary/src/xenia/emulator.cc#L376)): | 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`, symlink `scratch:` - `mount_cache` → `\CACHE0`, `\CACHE1`, `\CACHE` with `cache0:`, `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_cache` is on, host directories `cache/`, `cache0/`, `cache1/` back the partitions; otherwise they don't exist for the guest at all. - No `STFS` content 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](xenia-canary/src/xenia/gpu/graphics_system.cc#L79-L81): ```cpp register_file_ = reinterpret_cast(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](xenia-canary/src/xenia/gpu/command_processor.cc#L130-L148): 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](xenia-canary/src/xenia/gpu/graphics_system.cc#L135)), at step 6 of §0. It blocks on `write_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](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc#L313-L319)). ### 6.4 MMIO The GPU MMIO range `[0x7FC80000, 0xFFFF0000]` is hooked via `Memory::AddVirtualMappedRange` from `GraphicsSystem::Setup` ([graphics_system.cc:141-144](xenia-canary/src/xenia/gpu/graphics_system.cc#L141-L144)). 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::Setup` when `with_presentation=true` ([graphics_system.cc:116-128](xenia-canary/src/xenia/gpu/graphics_system.cc#L116-L128)). - `VdInitializeEngines` is stubbed to return 1 — xenia uses no real microcode ([xboxkrnl_video.cc:271-280](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc#L271-L280)). - 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](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc#L203-L219) 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](xenia-canary/src/xenia/apu/audio_system.cc#L48-L97)) called at step 7 of §0: - `queued_frames_` clamped to `[4, 64]` from cvar `apu_max_queued_frames` (default 8). - **256 client semaphores** allocated, initial count 0, max count = `queued_frames_`. - `shutdown_event_`, `resume_event_` created. - `XmaDecoder` instantiated; its `Setup()` runs. - Worker thread spawned, executing `WorkerThreadMain`, immediately parked on `WaitAny(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](xenia-canary/src/xenia/emulator.cc#L307)) initializes the input layer; per [src/xenia/hid/input_system.h:82-85](xenia-canary/src/xenia/hid/input_system.h#L82-L85): - `connected_slots = bitset(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. - `XInputGetCapabilities` on disconnected slots returns `X_ERROR_DEVICE_NOT_CONNECTED` ([input_system.cc:179](xenia-canary/src/xenia/hid/input_system.cc#L179)). 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](xenia-canary/src/xenia/kernel/xam/xam_net.cc#L173)). When queried via `NetDll_XNetGetTitleXnAddr` ([xam_net.cc:476-499](xenia-canary/src/xenia/kernel/xam/xam_net.cc#L476-L499)): - 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](xenia-canary/src/xenia/base/clock.cc#L39)) returns the host CPU tick frequency unless overridden by `clock_no_scaling`. Reported to guest by `KeQueryPerformanceFrequency_entry` ([xboxkrnl_threading.cc:438-443](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc#L438-L443)). - `KeQuerySystemTime_entry` ([xboxkrnl_threading.cc:483-497](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc#L483-L497)) reads `Clock::QueryGuestSystemTime` — wall clock as of emulator startup epoch. - `KeTimeStampBundle` (§3.2) is the cheap shared mailbox; updated by a repeating `HighResolutionTimer`. --- ## 11. Threading at Entry At the boundary, the threads that exist are: 1. **Main XThread** (`is_main_thread=true`, `guest_thread=true`) — currently suspended, about to be resumed. Stack range `0x70000000-0x7F000000`, host stack 16 MiB ([xthread.cc:420](xenia-canary/src/xenia/kernel/xthread.cc#L420)), priority/affinity set via `GetFakeCpuNumber` derived from `(creation_flags >> 24)` ([xthread.cc:395-396](xenia-canary/src/xenia/kernel/xthread.cc#L395-L396)). CPU index assigned via `SetActiveCpu(cpu_index)` ([xthread.cc:464](xenia-canary/src/xenia/kernel/xthread.cc#L464)). 2. **Kernel dispatch worker thread** — spawned in `SetExecutableModule` to handle guest async callbacks ([kernel_state.cc:368-391 ~](xenia-canary/src/xenia/kernel/kernel_state.cc#L368-L391)). Host-side; consumes from a host queue, does not appear in the guest object table. 3. **GPU command processor thread** — already running (parked on `write_ptr_index_event_`). 4. **Audio worker thread** — already running (parked on its semaphore set). 5. **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](xenia-canary/src/xenia/kernel/kernel_state.h#L233)). --- ## 12. JIT / Codegen State - Backend (x64 or AArch64) initialized at `Processor` construction. - `backend_->AllocThreadData()` and `InitializeBackendContext(context_)` called from `ThreadState` ctor ([thread_state.cc:77, 82](xenia-canary/src/xenia/cpu/thread_state.cc#L77-L82)). - Code cache empty — entry-point block JITs on first execution unless `enable_early_precompilation` cvar 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. `UsbdBootEnumerationDoneEvent` is allocated as a guest event in `KernelGuestGlobals` but its signaled-state at entry is the field default (verify against `KernelGuestGlobals` struct). - **Cache partition**: present only if `mount_cache` cvar set. - **System link / bridged LAN**: not initialized. - **Hypervisor surfaces / KdNet / DmEvents**: KD/network debug is not implemented. `DebugPrint` redirects into xenia's logger. - **Emulator-detection signals (intentional or accidental)**: `KeDebugMonitorData` always nonzero or known-zero (vs. real-HW behavior), missing/unimplemented kernel exports, exact MSR value `0x9030`, the constant r2=`0x20000000`, the fake XUID `0xB13EBABEBABEBABE`. --- ## 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 = ; 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: 1. **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](xenia-canary/src/xenia/kernel/xthread.cc#L389). That confirms `stack_base_`, `stack_limit_`, `thread_id_`. 2. **Drop into JIT entry breakpoint** — set a JIT-store probe (per AUDIT-067 pattern in memory) on the guest PC = `entry_point_` and dump the `PPCContext` once. Compare GPRs/VSCR/MSR against the table above. 3. **Pre-entry kernel-export dump** — print the contents of guest VAs for `XboxHardwareInfo`, `KeDebugMonitorData`, `KeTimeStampBundle`, `ExLoadedCommandLine` immediately before resuming the main thread; verify §3.1 expected bytes. 4. **VFS sanity** — `KernelState::file_system_->ResolvePath("game:\\default.xex")` should succeed; `D:` should resolve to the same device. 5. **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. 6. **Audio pre-state** — assert 256 client semaphores all have count=0, worker thread parked, no XMA contexts registered. 7. **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 `KernelGuestGlobals` *object-type* sub-structs (`ExThreadObjectType` etc.) — these are populated in `InitializeKernelGuestGlobals()`; full byte-level dump would require reading [kernel_state.cc:1511 onward](xenia-canary/src/xenia/kernel/kernel_state.cc#L1511) in full. - `XboxKrnlVersion` exact 8 bytes — held in `KernelVersion` static, 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_info` fields 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](xenia-canary/src/xenia/cpu/thread_state.cc) — PPC context init (canonical truth for GPRs/MSR/VSCR/VRSAVE). - [src/xenia/kernel/xthread.cc](xenia-canary/src/xenia/kernel/xthread.cc) — stack, TLS, KPCR, KTHREAD, host-thread creation, `Execute` dispatch. - [src/xenia/kernel/kernel_state.cc](xenia-canary/src/xenia/kernel/kernel_state.cc) — LaunchModule, SetExecutableModule, KernelGuestGlobals, KeTimeStampBundle. - [src/xenia/kernel/kernel_state.h](xenia-canary/src/xenia/kernel/kernel_state.h) — `KernelGuestGlobals` struct. - [src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc) — preinit'd guest-visible kernel-exported variables. - [src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc) — Vd* stubs. - [src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc](xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc) — KeQueryPerformanceFrequency / KeQuerySystemTime. - [src/xenia/kernel/xam/xam_net.cc](xenia-canary/src/xenia/kernel/xam/xam_net.cc) — XNADDR and network defaults. - [src/xenia/kernel/xam/user_profile.cc](xenia-canary/src/xenia/kernel/xam/user_profile.cc) — default user profile. - [src/xenia/kernel/user_module.cc](xenia-canary/src/xenia/kernel/user_module.cc) — XEX header parsing, entry_point extraction. - [src/xenia/emulator.cc](xenia-canary/src/xenia/emulator.cc) — Initialize/LaunchTitle subsystem order; VFS device factory. - [src/xenia/gpu/graphics_system.cc](xenia-canary/src/xenia/gpu/graphics_system.cc) — GPU setup. - [src/xenia/gpu/command_processor.cc](xenia-canary/src/xenia/gpu/command_processor.cc) — gamma ramp init, CP thread. - [src/xenia/apu/audio_system.cc](xenia-canary/src/xenia/apu/audio_system.cc) — audio worker, client semaphores. - [src/xenia/hid/input_system.h](xenia-canary/src/xenia/hid/input_system.h), [.cc](xenia-canary/src/xenia/hid/input_system.cc) — controller slots empty at entry. - [src/xenia/memory.cc](xenia-canary/src/xenia/memory.cc), [.h](xenia-canary/src/xenia/memory.h) — heap topology, physical mirrors. - [src/xenia/base/clock.cc](xenia-canary/src/xenia/base/clock.cc) — tick frequency, system time.