# MN103S / GDR-8050L Emulator Handoff — v258

This document is meant to be pasted or uploaded to the next agent before continuing work. It summarizes the project goal, the current known-good baseline, what has been proven, what has not been proven, and the next work target.

## Project goal

The immediate deliverable is a working GDR-8050L / MN103S-based Xbox DVD drive emulator that can:

1. Present to Windows as a single `HL-DT-ST DVD-ROM GDR8050L`-style optical device through the current iSCSI bridge.
2. Support the Xbox DVD authentication/unlock flow used by `unlockdrive.exe`.
3. Preserve locked-video partition behavior before unlock and unlocked Xbox game view after authentication.
4. Gradually replace bridge-side synthetic behavior with firmware-derived behavior from the GDR-8050L firmware.
5. Eventually aid reverse engineering and recipient-firmware work across related HLDS/MN103S drives.

The current workstream is **not** generic runner automation. It is focused on proving firmware READ/parser/descriptor behavior before moving to timer/MMIO modeling.

## Current stable baseline and version line

Known-good baseline:

- `v206_live_iscsi_stateful_eject_policy_update.zip`
- Known-good behavior confirmed by the user:
  - Windows sees a single emulated `HL-DT-ST DVD-ROM GDR8050L`.
  - VLC can play the locked/video partition before unlock.
  - `unlockdrive.exe` can unlock and see the Xbox game view.

Restored stable development line:

- v234 restored the stable runtime after v235-v249 Windows-runner instability.
- v250-v258 are firmware-proof/report/probe updates built on the v234 line.
- Avoid reusing v235-v249 automated runner ideas. Those versions caused Windows window/runner churn and should not be revived without explicit user direction.

Current latest package:

- `mn103s_emu_trace_v17_v258_read10_phase4_descriptor_consumer_probe_update.zip`

Current latest user live artifact:

- `gdr8050l_auth_v258_dynamic_iscsi_live_artifacts.zip`

## User testing policy going forward

Do **not** ask the user to run the full validation suite for every probe/report build.

Use this rule:

```text
Parser/probe/report-only change:
  run emulator + unlockdrive.exe only
  collect logs

SCSI handler / media mapping / iSCSI bridge / state machine change:
  run fuller live validation

New baseline candidate:
  run full known-good flow, including locked VLC, unlock, post-unlock view, and eject/reload when relevant
```

For the current v250-v258 proof work, quick `unlockdrive.exe` validation is acceptable.

Expected quick-smoke command pattern:

```powershell
.\gdr8050l_auth_v258_stateful_relock_keep_loaded_iscsi_start.cmd `
  .\gdr8050l_auth_v258_stateful_relock_keep_loaded_iscsi_config.json `
  "D:\vscode-workspace\xbox-dvd-tools-v2\disc_dumps\Red Faction II[TQ00501A].iso" `
  192.168.0.8 `
  3260
```

Then run the user's normal unlocker manually and collect:

```powershell
.\gdr8050l_auth_v258_dynamic_iscsi_collect_logs.ps1
```

Expected artifact naming pattern:

```text
gdr8050l_auth_v258_dynamic_iscsi_live_artifacts.zip
```

## v258 live result summary

The v258 artifact is good for the current quick-smoke validation scope.

Key trace results:

```text
rows: 265 total
SCSI command rows: 258
known_good_v206_complete: true
known_good_v206_eject_cycle_complete: false
check_condition_count: 0
expected_boundary_check_condition_count: 0
unexpected_check_condition_count: 0
```

The `known_good_v206_eject_cycle_complete=false` result is expected for the shorter quick-smoke run. It did not include the complete post-eject locked-boundary read sequence. It is not a regression by itself.

Regression checks from the trace report:

```text
single_lun_only: true
locked_capacity_seen: true
auth_challenge1_seen: true
auth_challenge2_seen: true
partition1_unlock_seen: true
sticky_descramble_seen: true
unlocked_capacity_seen: true
post_unlock_unlocked_capacity_seen: true
locked_direct_read_seen: true
unlocked_delta_read_seen: true
relock_eject_seen: true
keep_loaded_eject_seen: true
post_eject_locked_direct_read_seen: false
```

Command counts:

```text
TEST UNIT READY: 79
GET CONFIGURATION: 48
GET EVENT STATUS NOTIFICATION: 48
READ(10): 38
MODE SENSE(10): 8
MODE SELECT(10): 6
READ CAPACITY(10): 6
INQUIRY: 5
READ DVD STRUCTURE: 5
READ TOC/PMA/ATIP: 3
START STOP UNIT: 3
GET PERFORMANCE: 2
MODE SELECT(6): 2
PREVENT/ALLOW MEDIUM REMOVAL: 2
READ DISC INFORMATION: 1
REPORT LUNS: 1
SET CD SPEED: 1
```

Auth/state events observed:

```text
challenge1
challenge2
partition1_unlock
sticky_descramble_mode31
start_stop_eject
start_stop_load
challenge1
challenge2
partition1_unlock
sticky_descramble_mode31
start_stop_nop
```

Read-capacity observations:

```text
locked max LBA: 6991      sectors: 6992      block size: 2048
unlocked max LBA: 3431263 sectors: 3431264   block size: 2048
```

READ mapping observations:

```text
locked READ rows: 28      effective delta: 0
unlocked READ rows: 10    effective delta: 198144 / 0x00030600
old 0x306080 redump rows: 0
unexpected CHECK CONDITIONs: 0
```

Media/profile reports:

```text
media_profile_preflight: ok=true
media_profile_selftest: ok=true
media_payload_integrity: ok=true
standard_probe_coverage: ok=true
```

The local regression fleet report says `Overall OK: false`, but for this quick-smoke run that is caused by missing full-suite checks, especially the full eject/relock boundary sequence. Treat this as expected for unlocker-only validation unless the user explicitly ran the full suite.

## Important media-profile facts

Current Redump-style media profile for `Red Faction II[TQ00501A]`:

```text
layout_type: original_xbox_xgd1_redump_style_2048
sector_size: 2048
reconstructed_output_sector_count: 3820880
reconstructed_output_byte_count: 7825162240
layer_break_lba: 1913776
game_output_start_lba: 198144
game_xiso_leadin_sector_count: 32
xdfs_volume_lba_within_game_region: 32
game_unlocked_source_start_lba: 32
game_unlocked_source_sector_count: 3431232
video_l0_sector_count: 6832
video_l1_start_lba: 3820720
video_l1_sector_count: 160
locked_visible_sector_count: 6992
unlocked_visible_sector_count: 3431264
locked READ CAPACITY(10): 00001B4F00000800
unlocked READ CAPACITY(10): 00345B5F00000800
```

Payload integrity in v258:

```text
AD C0 present: true, size 1636
PFI present: true, size 2048
DMI present: true, size 2048
READ DVD STRUCTURE trace payload comparisons: compare_ok=true
```

Current bridge mapping still uses the media profile:

```text
locked window: host LBA maps directly to locked video regions
unlocked window: media_lba = host_lba + 198144
```

This mapping works, but the unlocked delta is **not yet firmware-derived**.

## Firmware READ/parser/descriptor proof status

### High-level status

Current honest proof status after v258:

```text
firmware_derived_host_lba: true
parser_descriptor_proof_complete_read10: true
single_call_stack_proof: false
firmware_derived_delta: false
```

Meaning:

- READ(10) host-LBA ingestion into firmware SRAM is proven.
- READ(10) descriptor handoff is proven across firmware state handoff.
- It is **not** proven as one uninterrupted front-dispatch-to-main-loop call stack.
- The unlocked Redump/media-window delta is still bridge/media-profile selected, not firmware-derived.

### Proven SRAM/firmware roles

Important SRAM cells:

```text
0x05D0 = command opcode / command state byte in several parser paths
0x05D2..0x05D5 = CDB-shadow LBA bytes used by READ(10) natural handler
0x05EC = assembled host LBA
0x05F0 = command/parser state; READ(10) natural handler sets 0x11
0x05B6 = descriptor gate/flags; mask 0x04 enables descriptor copy
0x06F1 = phase/state handoff; READ path sets 0x04
0x06F4 = command function pointer used by READ-class scheduler slice
0x06E0 = transfer/descriptor armed flag; descriptor path writes 0xF0
0x06E1 = descriptor metadata flag from state table
0x06E4 = descriptor LBA destination
0x06EC/0x06ED = state-table metadata fields
```

Important firmware PCs:

```text
0x9001C5F4 = front dispatcher
0x9001C710 = READ-class scheduler slice used by prior probes
0x9001EED0 = natural READ(10) handler
0x9002EA7C = READ(10) wrapper
0x90030687 = helper used by READ(10) handler while assembling LBA
0x9001B285 = main service loop / phase consumer entry used by v258
0x9003B9A0 = phase dispatch table
0x9001B4AE = phase 0x04 handler
0x9001B54E = descriptor setup/gate function
0x9001B5E8 = descriptor gate test on 0x05B6 mask 0x04
0x9001B5EF = descriptor copy block; reads 0x05EC
0x9001B5F2 = descriptor write area; writes 0x06E4
```

### Version-by-version proof chain

v250 — descriptor-builder microprobe:

```text
0x9001B5EF reads seeded SRAM 0x05EC
0x9001B5F2 writes descriptor SRAM 0x06E4
0x9001B5F8 writes 0x06E0 = 0xF0
```

This proved the descriptor copy block itself, but only via direct entry.

v251 — descriptor-gate microprobe:

```text
0x9001B54E enters descriptor setup
0x9001B5E8 tests SRAM 0x05B6 with mask 0x04
0x05B6 & 0x04 set -> reaches 0x9001B5EF and copies 0x05EC -> 0x06E4
0x05B6 & 0x04 clear -> skips descriptor copy
```

v252 — parser descriptor-state probe:

```text
READ parser path writes 0x05EC = assembled host LBA
READ parser path writes 0x05F0 = 0x0E
READ parser path writes 0x05D0 = READ opcode
READ parser path writes 0x06F1 = 0x04
seeded descriptor gate accepts that parser state if 0x05B6 & 0x04 is set
```

v253 — READ dispatch/handler probe:

```text
READ(10) opcode 0x28 -> class 0x48 -> wrapper 0x9002EA7C -> handler 0x9001EED0
0x9001EED0 reads CDB-shadow LBA from 0x05D2..0x05D5
0x9001EED0 writes assembled host LBA to 0x05EC
0x9001EED0 writes 0x05F0 = 0x11
0x9001EED0 writes 0x06F1 = 0x04
```

v254 — READ(10) state-0x11 descriptor probe:

```text
Descriptor setup accepts READ(10) natural handler state:
  0x05F0 = 0x11
  0x06F1 = 0x04
  0x05B6 & 0x04 set
Then copies 0x05EC -> 0x06E4 and arms 0x06E0 = 0xF0
```

v255 and v257 — scheduler/boundary correction:

- v255 initially tried to prove a natural scheduler-to-descriptor path.
- v257 corrected an important over-claim:

```text
READ(10) natural front-dispatch path reaches D2 = 0x48 and returns at 0x9001C714.
The descriptor branch at 0x9001C717 -> 0x9001C78A is gated on D2 = 0x30.
Static table audit shows D2/class 0x30 belongs to opcode 0x5A / MODE SENSE(10), not READ(10).
```

So do **not** claim that READ(10) naturally takes the D2=0x30 descriptor branch.

v256 — front dispatch closure:

```text
0x9001C5F4 reads opcode from 0x05D0
READ(10) 0x28 -> class 0x48 -> wrapper 0x9002EA7C -> handler 0x9001EED0
handler writes 0x05EC, 0x05F0=0x11, 0x06F1=0x04
```

READ(12) note from v256:

```text
normal table: READ(12) 0xA8 -> class 0x14 -> handler 0x9001C8C8
alternate table: READ(12) 0xA8 -> class 0x49 -> wrapper 0x9002EA89 -> common READ handler 0x9001EED0
```

v258 — READ(10) phase-4 descriptor consumer probe:

```text
v257/v253 proved READ(10) natural handler state:
  0x05EC = assembled host LBA
  0x05B6 & 0x04 set
  0x05F0 = 0x11
  0x06F1 = 0x04

v258 proves consumer side:
  0x9001B285 main service loop
  -> reads 0x06F1
  -> phase table 0x9003B9A0[4]
  -> 0x9001B4AE
  -> 0x9001B54E
  -> 0x9001B5EF
  -> copies 0x05EC to 0x06E4
  -> arms 0x06E0 = 0xF0
  -> clears 0x06F1
```

v258 local validation:

```text
[FIRMWARE-READ10-PHASE4-DESCRIPTOR] cases=5/5
phase4_consumer=true
parser_descriptor_read10=true
firmware_derived_delta=false
ok=true
```

## What is not proven yet

Do not overclaim any of these:

```text
firmware_derived_delta: false
single_call_stack_proof: false
READ(12) full parser/descriptor state-handoff closure: not fully complete
firmware window/selector that consumes auth state and derives unlocked mapping: not proven
```

The bridge currently uses:

```text
unlocked effective delta = 198144 / 0x00030600
```

That value is correct for the current Redump-style media profile and live behavior, but it remains a bridge/media-profile decision. A ROM occurrence of `0x00030600` is not sufficient proof unless an executed firmware window/selector path consumes it.

## Current next target

The user explicitly wants to finish parser/descriptor proof before moving to timer/MMIO modeling.

Best next target:

1. Keep v258 as the current parser/descriptor state-handoff closure for READ(10).
2. Audit whether READ(12) should get equivalent state-handoff closure or be explicitly documented as alternate/secondary.
3. Start the descriptor-output/window-selector proof:
   - begin after `0x06E4` has descriptor LBA and `0x06E0=0xF0`;
   - trace what consumes `0x06E4`, `0x06E0`, `0x06E1`, `0x06EC`, `0x06ED`;
   - identify whether a firmware path applies locked/unlocked window selection, layer/window translation, or source/media offset;
   - inspect candidates around state/window SRAM such as `0x0760` and `0x0780` and any ROM/table references found by static probes;
   - keep `firmware_derived_delta=false` until the firmware path itself computes or selects the unlocked media offset.

Do not jump to timer/MMIO until this descriptor-output/window-selector question is exhausted or explicitly deferred by the user.

## Timer/MMIO note for later

The user pointed out an important nuance:

```text
GDR HL0E smoke reaches the HL handler, then stalls in the known hardware/timer loop at 0x90006227..0x90006231.
That is not a parser failure. It means the discriminator passed and deeper execution now depends on better timer/MMIO modeling.
```

This should be handled later, after the current parser/descriptor proof work.

## Packaging and workflow rules

User preferences and project constraints:

- Use clean overlay ZIPs preserving target filenames.
- Do not include firmware binaries in update ZIPs.
- Do not include `.bin`, ISO/media payloads, `.pyc`, `__pycache__`, or stale old-version history data.
- Do not include v235-v249 automated runner changes.
- Avoid changing Windows runner plumbing unless absolutely necessary.
- Use stable canonical script names in installable ZIPs.
- Provide plain PowerShell commands without `PS ...>` prompt prefix.
- Do local/offline iteration first; only ask the user for a live run when there is a meaningful proof/runtime change.

## Useful source/document files in this project context

Commonly referenced uploaded technical files:

```text
/mnt/data/microcomputer_mn103s.pdf
/mnt/data/MN103S_Instruction_Set.pdf
/mnt/data/Panasonic MN103S User Manual.pdf
/mnt/data/SCSI-3-commandset.pdf
/mnt/data/GCC-4241N.pdf
/mnt/data/SST-39LFX00A.pdf
/mnt/data/M12L16161A.PDF
/mnt/data/0099_GDR-8050L_0L23_firmware_90000000_GDR-8050L_0L23_5af3ae9b_firmware_4c61eb12_plaintext_7cab0f5c.asm
/mnt/data/GDR-8050L_0L23_5af3ae9b_firmware_4c61eb12_plaintext_7cab0f5c.bin
/mnt/data/emu.cpp
/mnt/data/ana.cpp
/mnt/data/ins.cpp
/mnt/data/out.cpp
/mnt/data/reg.cpp
/mnt/data/ins.hpp
/mnt/data/mn103.cfg
/mnt/data/scsi1.pas
```

Use the firmware/disassembly and PDFs for emulator/CPU/MMIO correctness work. Treat current live bridge behavior as a test harness, not as final firmware truth.

## Current short instruction to the next agent

Continue from v258. Do not change runner plumbing. Do not move to timer/MMIO yet. The current task is to finish the parser/descriptor/window proof chain:

```text
READ(10) front dispatch/handler -> 0x05EC/0x05F0/0x06F1/0x05B6 is proven.
Phase-4 consumer -> descriptor setup -> 0x05EC copied to 0x06E4 and 0x06E0=0xF0 is proven.
Now find what consumes descriptor output and whether firmware, not the bridge, selects locked/unlocked media-window translation.
Keep firmware_derived_delta=false until that is proven.
```
