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:
195
audit-runs/phase-c6-call-name-divergence/diff-report.md
Normal file
195
audit-runs/phase-c6-call-name-divergence/diff-report.md
Normal 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 | 15 | 29 | 33 | 15 |
|
||||
| 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": 1702049452, "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": 465604490, "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=15`: payload.ord: canary=300 ours=601
|
||||
|
||||
**Pre-context (last 5 matching events):**
|
||||
```
|
||||
canary: [10] kernel.call NtQueryVolumeInformationFile
|
||||
ours: [10] kernel.call NtQueryVolumeInformationFile
|
||||
canary: [11] kernel.return NtQueryVolumeInformationFile
|
||||
ours: [11] kernel.return NtQueryVolumeInformationFile
|
||||
canary: [12] import.call RtlInitAnsiString
|
||||
ours: [12] import.call RtlInitAnsiString
|
||||
canary: [13] kernel.call RtlInitAnsiString
|
||||
ours: [13] kernel.call RtlInitAnsiString
|
||||
canary: [14] kernel.return RtlInitAnsiString
|
||||
ours: [14] kernel.return RtlInitAnsiString
|
||||
```
|
||||
|
||||
**Divergent event:**
|
||||
```
|
||||
canary: [15] import.call RtlInitAnsiString
|
||||
ours: [15] import.call StfsCreateDevice
|
||||
```
|
||||
|
||||
**Next event after the divergence (if any):**
|
||||
```
|
||||
canary: [16] kernel.call RtlInitAnsiString
|
||||
ours: [16] kernel.call StfsCreateDevice
|
||||
```
|
||||
|
||||
**Raw events (JSON):**
|
||||
```json
|
||||
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 729254300, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "RtlInitAnsiString", "ord": 300}, "schema_version": 1, "tid": 7, "tid_event_idx": 15}
|
||||
{"deterministic": true, "engine": "ours", "guest_cycle": 4231, "host_ns": 465837253, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "StfsCreateDevice", "ord": 601}, "schema_version": 1, "tid": 2, "tid_event_idx": 15}
|
||||
```
|
||||
|
||||
## 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": 493283518, "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": 1702232923, "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).
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
1301
audit-runs/phase-c6-call-name-divergence/fix.diff
Normal file
1301
audit-runs/phase-c6-call-name-divergence/fix.diff
Normal file
File diff suppressed because it is too large
Load Diff
182
audit-runs/phase-c6-call-name-divergence/investigation.md
Normal file
182
audit-runs/phase-c6-call-name-divergence/investigation.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Phase C+6 — investigation: call-name divergence at idx=102132
|
||||
|
||||
## Divergence
|
||||
|
||||
| | canary | ours (pre-fix) |
|
||||
|---|---|---|
|
||||
| `import.call` at idx=102132, tid=6→1 | `NtClose` (ord 207) | `IoDismountVolumeByFileHandle` (ord 60) |
|
||||
|
||||
## Phase 0 — Rule out ord→name lookup bug
|
||||
|
||||
Both engines map ord 0x3C (60) to `IoDismountVolumeByFileHandle` and
|
||||
ord 0xCF (207) to `NtClose`. Cross-check:
|
||||
|
||||
* `xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_table.inc:74`
|
||||
`XE_EXPORT(xboxkrnl, 0x0000003C, IoDismountVolumeByFileHandle, kFunction)`
|
||||
* `xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_table.inc:221`
|
||||
`XE_EXPORT(xboxkrnl, 0x000000CF, NtClose, kFunction)`
|
||||
* `xenia-rs/crates/xenia-kernel/src/exports.rs:31`
|
||||
`register_export(Xboxkrnl, 0x3C, "IoDismountVolumeByFileHandle", stub_success)`
|
||||
* `xenia-rs/crates/xenia-kernel/src/exports.rs:91`
|
||||
`register_export(Xboxkrnl, 0xCF, "NtClose", nt_close)`
|
||||
|
||||
Ord→name mapping is byte-identical. **Phase 0 rules out emitter
|
||||
name-lookup bug.** This is a real event-stream divergence.
|
||||
|
||||
## Phase 1 — Capture context around idx=102132 in both streams
|
||||
|
||||
`audit-runs/phase-c5-NtWriteFile/ours.jsonl` lines 102134..102137
|
||||
(idx 102132..102135) and `phase-c-first-divergence/phase-a/canary.jsonl`
|
||||
matching tid=6 events:
|
||||
|
||||
```
|
||||
ours[102132] import.call IoDismountVolumeByFileHandle (ord 60)
|
||||
ours[102133] kernel.call IoDismountVolumeByFileHandle
|
||||
ours[102134] kernel.return IoDismountVolumeByFileHandle returns 0
|
||||
ours[102135] import.call NtClose (ord 207)
|
||||
ours[102136] kernel.call NtClose
|
||||
ours[102137] kernel.return NtClose returns 0
|
||||
|
||||
canary[102132] import.call NtClose (ord 207)
|
||||
canary[102133] kernel.call NtClose
|
||||
canary[102134] kernel.return NtClose returns 0
|
||||
canary[102135] import.call NtOpenFile (ord 223)
|
||||
```
|
||||
|
||||
**Observation**: Ours's events 102135..102137 (`NtClose` triple) are
|
||||
bit-identical to canary's events 102132..102134. Ours has 3 EXTRA
|
||||
events (`IoDismountVolumeByFileHandle` triple) injected at idx=102132
|
||||
that canary's stream does NOT contain. After ours's 3-event surplus,
|
||||
both streams realign: `ours[102138] = canary[102135] = NtOpenFile`.
|
||||
|
||||
So the game DOES call IoDismountVolumeByFileHandle in BOTH engines; the
|
||||
difference is purely whether the Phase A emitter fires.
|
||||
|
||||
## Phase 2 — Source-read both emitter paths
|
||||
|
||||
### Canary emit logic (path A: declared export)
|
||||
|
||||
`xenia-canary/src/xenia/kernel/util/shim_utils.h:597-602`:
|
||||
|
||||
```cpp
|
||||
const bool phase_a_on = phase_a_bridge::Enabled();
|
||||
if (phase_a_on) {
|
||||
phase_a_bridge::EmitImportAndCall(
|
||||
phase_a_bridge::KernelModuleIdName(MODULE), ORDINAL,
|
||||
export_entry->name);
|
||||
}
|
||||
```
|
||||
|
||||
Inside `Trampoline`, only reachable when a `DECLARE_XBOXKRNL_EXPORT`
|
||||
shim wires `export_entry->function_data.trampoline = &X::Trampoline`.
|
||||
|
||||
### Canary emit logic (path B: table-entry-only, no DECLARE)
|
||||
|
||||
`xenia-canary/src/xenia/cpu/xex_module.cc:1310-1335` import-thunk
|
||||
generator: when `kernel_export->function_data.trampoline == nullptr`
|
||||
(no DECLARE shim), the thunk is rewritten to `sc 2; blr` — the syscall
|
||||
form. The "extern handler" wired in `SetupExtern(handler=nullptr, ...)`
|
||||
forwards the call to `PPCFrontend::SyscallHandler`
|
||||
(`ppc_frontend.cc:83-92`):
|
||||
|
||||
```cpp
|
||||
void SyscallHandler(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||
uint64_t syscall_number = ppc_context->r[0];
|
||||
switch (syscall_number) {
|
||||
default:
|
||||
assert_unhandled_case(syscall_number);
|
||||
XELOGE("Unhandled syscall {}!", syscall_number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
No `phase_a_bridge::EmitImportAndCall` call. **Canary emits NO Phase A
|
||||
events for table-entry-only exports.** Verified by grepping
|
||||
xenia-canary for `DECLARE_XBOXKRNL_EXPORT` declarations — only 287
|
||||
ords have implementations; `IoDismountVolumeByFileHandle` is NOT among
|
||||
them. (See `/tmp/canary_decl.txt` snapshot in `investigation.md`'s
|
||||
work artifacts.)
|
||||
|
||||
### Ours emit logic
|
||||
|
||||
`xenia-rs/crates/xenia-kernel/src/state.rs:585-632` (pre-fix):
|
||||
|
||||
```rust
|
||||
if let Some(&(name, func)) = self.exports.get(&(module, ordinal)) {
|
||||
...
|
||||
let phase_a_on = crate::event_log::is_enabled();
|
||||
...
|
||||
if phase_a_on {
|
||||
crate::event_log::emit_import_call(...);
|
||||
crate::event_log::emit_kernel_call(...);
|
||||
}
|
||||
func(&mut ctx, mem, self);
|
||||
if phase_a_on {
|
||||
let return_value = if is_void { 0 } else { ctx.gpr[3] };
|
||||
crate::event_log::emit_kernel_return(...);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ours emits `import.call`/`kernel.call`/`kernel.return` for EVERY
|
||||
registered ord, regardless of whether canary has a real shim or
|
||||
a syscall-thunk. `IoDismountVolumeByFileHandle` is registered as
|
||||
`stub_success` and therefore generates 3 spurious Phase A events.
|
||||
|
||||
## Phase 3 — Classification
|
||||
|
||||
**Class (E) Phase A emitter framing — Phase A coverage gap.** Ours's
|
||||
emitter fires for stubs that canary leaves silent (canary uses the
|
||||
syscall thunk for table-entry-only exports, which does not reach
|
||||
`Trampoline`).
|
||||
|
||||
Not class (A) (no guest-code branch flip — events realign at +3),
|
||||
not class (α) (this is not canonicalization — it's an emitter
|
||||
asymmetry that we can fix at source), not class (D) (no deferred-
|
||||
item interaction — heap region / clock not involved).
|
||||
|
||||
## Sister bugs surfaced (out-of-scope — documented for follow-up)
|
||||
|
||||
`comm -23 <ours-xboxkrnl> <canary-DECLARE_XBOXKRNL_EXPORT>` lists
|
||||
**12 xboxkrnl ords** ours registers that canary doesn't have a shim
|
||||
for. Of those, the following actually fire in the current 50M run
|
||||
and would also drift Phase A alignment if their callers reached them:
|
||||
|
||||
* `IoDismountVolumeByFileHandle` (ord 0x3C, called 1× tid=1 main —
|
||||
**fixed in this session**)
|
||||
* `StfsCreateDevice` (ord 0x259, called 1× tid=2 — drives tid=7→tid=2
|
||||
divergence at idx=15; out of scope per session-scope rule)
|
||||
|
||||
The other 10 (DbgPrint, RtlCaptureContext, RtlUnwind, sprintf,
|
||||
_vsnprintf, __C_specific_handler, XeKeysConsoleSignatureVerification,
|
||||
StfsControlDevice) are not yet called in the 50M run; they will
|
||||
become relevant only after the game progresses further.
|
||||
|
||||
**Sister bug (different class)**: ord 0x82 is `KeQueryInterruptTime`
|
||||
in canary but ours mis-labels it `KeQueryIdealProcessor`; ord 0x98 is
|
||||
`KeSetBackgroundProcessors` in canary but ours mis-labels it
|
||||
`KeSetIdealProcessor`. These are name-lookup bugs (Stage 2 cleanup
|
||||
class) and are NOT addressed here; would require renaming the
|
||||
function-pointer fn and either dropping the existing semantics or
|
||||
moving them to a different ord.
|
||||
|
||||
## Reading-error class #26 (additive)
|
||||
|
||||
**Phase A emitter coverage asymmetry across the "table-entry-only"
|
||||
vs "shim-implemented" axis.** Canary's emitter fires only from
|
||||
`Trampoline` (wired by `DECLARE_XBOXKRNL_EXPORT`). Ours's emitter
|
||||
fires for every `register_export` regardless of canary equivalence.
|
||||
When a guest import is in canary's table but has no DECLARE shim,
|
||||
canary routes it through a no-op syscall thunk with no Phase A
|
||||
emission — ours, by registering a `stub_success`, injects 3 spurious
|
||||
events per call.
|
||||
|
||||
Discipline addition: when registering a kernel export as
|
||||
`stub_success`/`stub_return_zero` etc., grep canary for
|
||||
`DECLARE_XBOXKRNL_EXPORT(<name>` first. If absent, use
|
||||
`register_unimplemented_export` instead of `register_export` so the
|
||||
Phase A emitter stays silent (matching canary). Reading-error #21
|
||||
(C+1's `gpr[3]`-as-return-value for void exports) and #25 (C+5's
|
||||
wrong-register read) were both kernel-export-emitter bugs; this is
|
||||
the third in that family.
|
||||
114
audit-runs/phase-c6-call-name-divergence/re-validation.md
Normal file
114
audit-runs/phase-c6-call-name-divergence/re-validation.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Phase C+6 — re-validation
|
||||
|
||||
## Gate 1 — Determinism (cvar-OFF, ours)
|
||||
|
||||
3 fresh runs of `check -n 50000000 --stable-digest`:
|
||||
|
||||
| run | digest md5 |
|
||||
|-----|------------|
|
||||
| 1 | c6d895829b4611964978990ae1cb8a6a |
|
||||
| 2 | c6d895829b4611964978990ae1cb8a6a |
|
||||
| 3 | c6d895829b4611964978990ae1cb8a6a |
|
||||
| C+5 baseline (cvar-OFF) | `c6d895829b4611964978990ae1cb8a6a` |
|
||||
|
||||
**Result**: ✅ byte-identical across 3 runs and SAME as the C+5
|
||||
baseline. The Phase C+6 fix is purely an emitter-framing change (cvar
|
||||
`phase_a_event_log` OFF path): the `unimplemented_exports` HashSet is
|
||||
consulted only inside the `phase_a_on` guard in `call_export`. The
|
||||
stub body (`stub_success`, which sets `r3 = 0`) still runs unchanged.
|
||||
Therefore the cvar-OFF deterministic boot trajectory is unchanged.
|
||||
Baseline digest preserved.
|
||||
|
||||
## Gate 2 — Phase B `image_canonical_sha256`
|
||||
|
||||
Phase B snapshot captured to `snap/ours/`.
|
||||
`image_loaded_sha256 = ea8d160e9369328a5b922258a92113efb8d7ce3e1a5c12cc521e375985c91c18`
|
||||
matches the Phase-A/B verify baseline. The fix touches only the
|
||||
kernel-export shim/emitter layer — no PE image bytes modified.
|
||||
|
||||
## Gate 3 — Phase A matched-prefix extension (KEY METRIC)
|
||||
|
||||
Diffed `audit-runs/phase-c6-call-name-divergence/ours.jsonl` against
|
||||
the existing `phase-c-first-divergence/phase-a/canary.jsonl`.
|
||||
|
||||
| chain | C+5 (pre-C+6) | C+6 (post) | Δ |
|
||||
|---|---|---|---|
|
||||
| canary tid=6 → ours tid=1 (main) | 102132 | **102158** | **+26** |
|
||||
| canary tid=4 → ours tid=11 | 5 | 5 | 0 |
|
||||
| canary tid=7 → ours tid=2 | 15 | 15 | 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 |
|
||||
|
||||
**Main thread matched prefix grew from 102132 to 102158. Gate 3 ✅.**
|
||||
|
||||
The new first-divergence at idx=102158 is `XamTaskCloseHandle`
|
||||
`return_value`: canary=1, ours=0 — value divergence, NOT a call-name
|
||||
divergence. That's the next Phase C+N target.
|
||||
|
||||
## Gate 4 — Build
|
||||
|
||||
```
|
||||
$ cargo build --release
|
||||
Compiling xenia-kernel v0.1.0
|
||||
Compiling xenia-app v0.1.0
|
||||
Finished `release` profile [optimized] target(s) in 6.22s
|
||||
```
|
||||
|
||||
One pre-existing dead-code warning (`walk_committed_regions`); not
|
||||
introduced by this fix. Canary untouched.
|
||||
|
||||
## Gate 5 — Phase A determinism (emitter)
|
||||
|
||||
Two cvar-ON captures of the same engine binary on the same ISO,
|
||||
md5-summing only deterministic fields (excluding `host_ns` AND
|
||||
`guest_cycle` — both are timing-sensitive, see Stage 2's
|
||||
established practice):
|
||||
|
||||
```
|
||||
ours.jsonl (run 1, det-fields-only) 7312446e49fa3c3149d26424832cabf4
|
||||
/tmp/c6_pa_run2.jsonl (run 2, det-fields-only) 7312446e49fa3c3149d26424832cabf4
|
||||
```
|
||||
|
||||
Byte-identical. ✅
|
||||
|
||||
Note: digest changes from C+5's `388d394a…` because the suppression
|
||||
flips 3 events on/off in the deterministic-fields stream. Expected.
|
||||
|
||||
## Gate 6 — Kernel unit tests
|
||||
|
||||
```
|
||||
$ cargo test --release -p xenia-kernel --lib
|
||||
test result: ok. 145 passed; 0 failed; 0 ignored; 0 measured;
|
||||
0 filtered out
|
||||
```
|
||||
|
||||
1 new test added (144 → 145):
|
||||
|
||||
* `register_unimplemented_export_marks_set_membership` — verifies the
|
||||
new `register_unimplemented_export` API both installs the export
|
||||
func (so `call_export` finds and runs the stub) AND inserts the
|
||||
`(module, ord)` pair into `unimplemented_exports` (so the Phase A
|
||||
emitter guard suppresses events). Cross-checks the negative case:
|
||||
a normal `register_export` does NOT mark unimplemented.
|
||||
|
||||
Full workspace test suite (`cargo test --release --workspace`):
|
||||
no regressions.
|
||||
|
||||
## Summary
|
||||
|
||||
All 6 gates pass. Phase A main matched prefix grew from 102132 to
|
||||
102158 (+26 events). One class-E (Phase A coverage gap) engine bug
|
||||
fixed: ours's emitter injected 3 spurious events
|
||||
(`import.call`/`kernel.call`/`kernel.return`) for
|
||||
`IoDismountVolumeByFileHandle` because canary's syscall-thunk path
|
||||
for table-entry-only exports never reaches `Trampoline` and emits
|
||||
nothing. New `register_unimplemented_export` API in `state.rs` lets
|
||||
us mark such exports for Phase A suppression while keeping their
|
||||
stub body execution intact. Cvar-OFF inert.
|
||||
|
||||
Diff-tool unchanged. Canary unchanged.
|
||||
|
||||
Next divergence: **XamTaskCloseHandle return value at
|
||||
tid_event_idx=102158** (canary=1, ours=0 — value divergence). Phase
|
||||
C+7 target.
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"build_id": "ours-phaseB",
|
||||
"cvars": {
|
||||
"phase_b_dump_section_content": false,
|
||||
"phase_b_snapshot_and_exit": true,
|
||||
"phase_b_snapshot_dir": "/home/fabi/RE - Project Sylpheed/xenia-rs/audit-runs/phase-c6-call-name-divergence/snap"
|
||||
},
|
||||
"deterministic_skip": [
|
||||
"host_ns_at_snapshot",
|
||||
"wall_clock_iso8601",
|
||||
"build_id",
|
||||
"iso_path",
|
||||
"cvars.phase_b_snapshot_dir"
|
||||
],
|
||||
"engine": "ours",
|
||||
"host_ns_at_snapshot": 0,
|
||||
"image_loaded_sha256": "ea8d160e9369328a5b922258a92113efb8d7ce3e1a5c12cc521e375985c91c18",
|
||||
"iso_path": "",
|
||||
"schema_version": 1,
|
||||
"wall_clock_iso8601": "epoch:0",
|
||||
"xex_entry_point": "0x824ab748",
|
||||
"xex_header_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"xex_image_base": "0x82000000",
|
||||
"xex_image_size": 9568256
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
{
|
||||
"cr": [
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0"
|
||||
],
|
||||
"ctr": "0x0000000000000000",
|
||||
"deterministic_skip": [
|
||||
"hw_id"
|
||||
],
|
||||
"engine": "ours",
|
||||
"fpr": [
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000"
|
||||
],
|
||||
"fpscr": "0x00000000",
|
||||
"gpr": [
|
||||
"0x0000000000000000",
|
||||
"0x00000000700fff00",
|
||||
"0x0000000020000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x000000007fff0000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000",
|
||||
"0x0000000000000000"
|
||||
],
|
||||
"hw_id": 0,
|
||||
"lr": "0x00000000bcbcbcbc",
|
||||
"msr": "0x0000000000009030",
|
||||
"pc": "0x824ab748",
|
||||
"pcr_base": "0x7fff0000",
|
||||
"schema_version": 1,
|
||||
"stack_base": "0x00000000",
|
||||
"stack_limit": "0x00000000",
|
||||
"thread_id": 1,
|
||||
"tls_base": "0x00000000",
|
||||
"vr": [
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000",
|
||||
"00000000000000000000000000000000"
|
||||
],
|
||||
"vrsave": "0xffffffff",
|
||||
"vscr": "00000000000000000000000000010000",
|
||||
"xer": {
|
||||
"ca": 0,
|
||||
"ov": 0,
|
||||
"so": 0,
|
||||
"tbc": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"deterministic_skip": [
|
||||
"raw_handle_id",
|
||||
"exports_registered_count"
|
||||
],
|
||||
"engine": "ours",
|
||||
"exports_registered_count": 199,
|
||||
"exports_registered_sample": [
|
||||
"xam.xex!NetDll_WSACleanup",
|
||||
"xam.xex!NetDll_WSAStartup",
|
||||
"xam.xex!XGetAVPack",
|
||||
"xam.xex!XGetGameRegion",
|
||||
"xam.xex!XGetLanguage",
|
||||
"xam.xex!XGetVideoMode",
|
||||
"xam.xex!XMsgInProcessCall",
|
||||
"xam.xex!XMsgStartIORequest",
|
||||
"xam.xex!XMsgStartIORequestEx",
|
||||
"xam.xex!XNotifyGetNext",
|
||||
"xam.xex!XNotifyPositionUI",
|
||||
"xam.xex!XamAlloc",
|
||||
"xam.xex!XamContentClose",
|
||||
"xam.xex!XamContentCreate",
|
||||
"xam.xex!XamContentCreateEnumerator",
|
||||
"xam.xex!XamContentDelete",
|
||||
"xam.xex!XamContentGetCreator",
|
||||
"xam.xex!XamContentGetDeviceData",
|
||||
"xam.xex!XamContentGetDeviceName",
|
||||
"xam.xex!XamContentGetDeviceState",
|
||||
"xam.xex!XamContentSetThumbnail",
|
||||
"xam.xex!XamEnableInactivityProcessing",
|
||||
"xam.xex!XamEnumerate",
|
||||
"xam.xex!XamFree",
|
||||
"xam.xex!XamGetExecutionId",
|
||||
"xam.xex!XamGetSystemVersion",
|
||||
"xam.xex!XamInputGetCapabilities",
|
||||
"xam.xex!XamInputGetKeystrokeEx",
|
||||
"xam.xex!XamInputGetState",
|
||||
"xam.xex!XamInputSetState",
|
||||
"xam.xex!XamLoaderLaunchTitle",
|
||||
"xam.xex!XamLoaderTerminateTitle"
|
||||
],
|
||||
"exports_registered_sha256": "bb97815f82b2313c9eaa07bf80dab47c5c23408c24203a1283dfb2aba1e84e09",
|
||||
"handle_name_table": [],
|
||||
"notification_listeners": [],
|
||||
"objects": [
|
||||
{
|
||||
"details": {
|
||||
"entry_pc": "0x824ab748",
|
||||
"exit_code": null,
|
||||
"hw_id": 0,
|
||||
"is_entry_thread": true,
|
||||
"thread_id": 1
|
||||
},
|
||||
"handle_semantic_id": "9879c5053fedb1d0",
|
||||
"name": null,
|
||||
"raw_handle_id": "0x00001000",
|
||||
"type": "Thread",
|
||||
"type_code": 5
|
||||
}
|
||||
],
|
||||
"schema_version": 1
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"engine": "ours",
|
||||
"files": {
|
||||
"config.json": "b80bb29cd9db114960218600f004eb10d6bdc8ad4b06894fe0461e19f12582fe",
|
||||
"cpu_state.json": "4e6df54ca1939d08854f3a52b49ed2c5ee0823d63cdecad8a7395203dac5443a",
|
||||
"kernel.json": "b64ea3a6c14f1b0aaadc6de8adbb894edf636a813120d08028ca096e1d06bacc",
|
||||
"memory.json": "b96ae4daebfbdd314e574492c1e162f532fa4f89ff5c0d7c6c29743797089cf1",
|
||||
"vfs.json": "97bb2bda57266d8e0dd1da13309eab5ece43130ef378a0b682917d299e9dc4e1"
|
||||
},
|
||||
"schema_version": 1
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"committed_pages_total": 2594,
|
||||
"deterministic_skip": [
|
||||
"host_base_pointer"
|
||||
],
|
||||
"engine": "ours",
|
||||
"guest_address_space_bytes": 4294967296,
|
||||
"heaps": [
|
||||
{
|
||||
"base": "0x00000000",
|
||||
"name": "v00000000",
|
||||
"page_size": 4096,
|
||||
"page_state_histogram": {
|
||||
"committed": 0
|
||||
},
|
||||
"size": "0x40000000"
|
||||
},
|
||||
{
|
||||
"base": "0x40000000",
|
||||
"name": "v40000000",
|
||||
"page_size": 4096,
|
||||
"page_state_histogram": {
|
||||
"committed": 266
|
||||
},
|
||||
"size": "0x40000000"
|
||||
},
|
||||
{
|
||||
"base": "0x80000000",
|
||||
"name": "v80000000",
|
||||
"page_size": 4096,
|
||||
"page_state_histogram": {
|
||||
"committed": 2336
|
||||
},
|
||||
"size": "0x40000000"
|
||||
},
|
||||
{
|
||||
"base": "0x90000000",
|
||||
"name": "v90000000",
|
||||
"page_size": 4096,
|
||||
"page_state_histogram": {
|
||||
"committed": 0
|
||||
},
|
||||
"size": "0x40000000"
|
||||
}
|
||||
],
|
||||
"page_size": 4096,
|
||||
"regions": [
|
||||
{
|
||||
"byte_count": 1048576,
|
||||
"end": "0x70100000",
|
||||
"protect": 0,
|
||||
"section_kind": null,
|
||||
"sha256": "30e14955ebf1352266dc2ff8067e68104607e750abb9d3b36582b8af909fcb58",
|
||||
"start": "0x70000000"
|
||||
},
|
||||
{
|
||||
"byte_count": 4096,
|
||||
"end": "0x7ffe1000",
|
||||
"protect": 0,
|
||||
"section_kind": null,
|
||||
"sha256": "ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7",
|
||||
"start": "0x7ffe0000"
|
||||
},
|
||||
{
|
||||
"byte_count": 4096,
|
||||
"end": "0x7fff1000",
|
||||
"protect": 0,
|
||||
"section_kind": null,
|
||||
"sha256": "e35cddaf9c210aed7505ec4cf1c599f58ac2b7ec25b0885db1ee49aba2db519a",
|
||||
"start": "0x7fff0000"
|
||||
},
|
||||
{
|
||||
"byte_count": 9568256,
|
||||
"end": "0x82920000",
|
||||
"protect": 0,
|
||||
"section_kind": null,
|
||||
"sha256": "ea8d160e9369328a5b922258a92113efb8d7ce3e1a5c12cc521e375985c91c18",
|
||||
"start": "0x82000000"
|
||||
}
|
||||
],
|
||||
"regions_walked": [],
|
||||
"schema_version": 1,
|
||||
"section_contents": null
|
||||
}
|
||||
71
audit-runs/phase-c6-call-name-divergence/snap/ours/vfs.json
Normal file
71
audit-runs/phase-c6-call-name-divergence/snap/ours/vfs.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"cache_root_listing": [],
|
||||
"deterministic_skip": [
|
||||
"host_path_realpath"
|
||||
],
|
||||
"engine": "ours",
|
||||
"mounted_devices_observed_count": 1,
|
||||
"resolve_path_probes": [
|
||||
{
|
||||
"is_directory": true,
|
||||
"path": "\\Device\\Cdrom0",
|
||||
"resolved": true,
|
||||
"size": null
|
||||
},
|
||||
{
|
||||
"is_directory": true,
|
||||
"path": "\\Device\\Cdrom0\\dat",
|
||||
"resolved": true,
|
||||
"size": 4096
|
||||
},
|
||||
{
|
||||
"is_directory": null,
|
||||
"path": "\\Device\\Cdrom0\\dat\\movie",
|
||||
"resolved": false,
|
||||
"size": null
|
||||
},
|
||||
{
|
||||
"is_directory": null,
|
||||
"path": "\\Device\\Cdrom0\\dat\\movie\\opening.bik",
|
||||
"resolved": false,
|
||||
"size": null
|
||||
},
|
||||
{
|
||||
"is_directory": false,
|
||||
"path": "\\Device\\Cdrom0\\default.xex",
|
||||
"resolved": true,
|
||||
"size": 3497984
|
||||
},
|
||||
{
|
||||
"is_directory": null,
|
||||
"path": "\\Device\\HardDisk0\\Partition1",
|
||||
"resolved": false,
|
||||
"size": null
|
||||
},
|
||||
{
|
||||
"is_directory": true,
|
||||
"path": "cache:\\",
|
||||
"resolved": true,
|
||||
"size": null
|
||||
},
|
||||
{
|
||||
"is_directory": null,
|
||||
"path": "cache:\\nonexistent_probe",
|
||||
"resolved": false,
|
||||
"size": null
|
||||
},
|
||||
{
|
||||
"is_directory": true,
|
||||
"path": "game:\\dat",
|
||||
"resolved": true,
|
||||
"size": 4096
|
||||
},
|
||||
{
|
||||
"is_directory": false,
|
||||
"path": "game:\\default.xex",
|
||||
"resolved": true,
|
||||
"size": 3497984
|
||||
}
|
||||
],
|
||||
"schema_version": 1
|
||||
}
|
||||
Reference in New Issue
Block a user