# Embedded mission setup: translated effects and checks

The seven FE-prefixed x86 blocks in four archive-04 records now have explicit effect descriptions in [scenarios.json](../analysis/missions/scenarios.json), readable reference operations in [mission_native.py](../tools/mission_native.py), and byte-addressed disassembly plus differential results in [native-verification.json](../analysis/missions/native-verification.json). The scenario browser displays the descriptions beside the stored setup.

All offsets below are offsets in the decompressed resource. Object offsets refer to the original 112-byte runtime object, accessed through SS:BP. Object 0 is the player; other indices follow setup allocation order across all three groups. **BP is the most recently allocated object**, not invariably the player.

## Native calling convention

`BE12–BE19` saves AX, sets BX to the helper-pointer table at `BEDD`, and calls SI. Every observed block advances SI by its own length. Some return directly; others tail-call a helper through BX. The parser restores AX, preserving its counted-object total.

| Pointer | Handler | Effect |
| --- | --- | --- |
| BEDD | C79D | Initialise boost/weapon energy, active boost, pitch, and placement |
| BEDF | 8E24 | Set motion parameters, two clock-relative fields and callback 8DDD |
| BEE1 | 5E59 | Write AL to weapon-1 counters 5E14 and 5E11 |

`C79D` stores DX to boost reserve `8540` and weapon energy `7FA6`. Its **incoming carry flag** selects active boost high byte `7F0E`: clear gives 0; set gives 28h. AX sets pitch. It then enters `C7C8`, which subtracts the current model's header word at +7 from CX to produce the object's height, stores DI as heading, and refreshes cell and position caches. This model-dependent adjustment must survive a faithful reconstruction.

## The seven blocks

| Resource / record / block | Current object | Effects |
| --- | --- | --- |
| 04_012 / 2 / 1AAC | Player | Speed magnitude 200, forward velocity 400; clear flag bit 4; pitch FF00, heading EC00, nominal height 2560; empty boost and weapon energy |
| 04_012 / 4 / 1D51 | Player | Sub-cell X=C8, Y=BB; rewrite following objects 1 and 2 to the player's cell; pitch 0, heading 0F20, nominal height 264; empty boost and weapon energy |
| 04_012 / 4 / 1D80 | Object 1 | Increment height high byte, equivalent to adding 256 with 16-bit wrap |
| 04_012 / 4 / 1D95 | Object 2 | Sub-cell X=4B, Y=46; subtract 2400 from height; speed magnitude 200, pitch 0C00; install callback 8DDD |
| 04_014 / 2 / 0F91 | Player | Speed magnitude 300, forward velocity 600; clear flag bit 4 and weapon-1 counters; pitch FE00, preserve heading, nominal height 4096; empty boost and weapon energy |
| 04_015 / 0 / 0028 | Player | Patch later native instruction with player's model pointer; clear flag bit 4; pitch F500, preserve heading, nominal height 2432; boost/weapon energy 9FFF and active boost high byte 28 |
| 04_015 / 0 / 0060 | Object 2 | Assign the model pointer embedded by the earlier block |

All pitch/heading values in the table are raw hexadecimal words; other quantities are decimal unless indicated. The descriptions intentionally avoid assigning scene identities from motion alone.

Two dependencies are particularly important:

- **1D51 modifies future object records.** After advancing SI to 1D79, it writes the player's X cell byte to SI+3 and SI+11h, and Y to SI+5 and SI+12h. These are the high bytes of object 1's absolute coordinates and the cell bytes of object 2's moving-object template. Their original sub-cell values are retained. The map still displays stored source coordinates and labels that limitation.
- **0028 modifies future executable code.** After advancing SI to 0044, it copies the player's model pointer to SI+22h = resource offset **0066**, the immediate operand of `MOV word ptr [BP+22h], imm16` in block 0060. On disk that immediate is zero. The later block gives object 2 the player's model pointer; it does not copy mesh data or the rest of the player's object definition.

For 1D95, helper `8E24` stores clock+256 at object +68, clock+1024 at +5E, and 8DDD at +66, all with 16-bit wrap. Callback `8DDD` calls movement helpers and compares the live clock against +5E using a signed difference; on expiry it changes the callback to 8823 and clears flag bit 4. Its complete subsequent movement is outside this setup check.

## Script boundary findings

**Opcode 38: conditional altitude operand.** Handler `C194` toggles bit 7 of `7ED2`. When the bit becomes set, it consumes a little-endian height word into `80AC`; when clear, it consumes no operand. Initial reset `3C43` clears the flag. The ordinary A-key handler changes bit 0, not bit 7.

In `04_015 / 0`, resource offset **039B** enables height **0200h** and continues at **039E**. Offset **03CC** disables the mode; **03CD** is already the next opcode (`12`, beacon-row change). Propagating this state recovers 65 additional instructions across the record's reached paths. The decoder tracks state through relative jumps and reports conflicting boundaries if encountered. Entry roots assume the reset high bit; this is not proof of all interleavings of concurrently running scripts or arbitrary entry into a supplementary record.

**Terminal counter wait.** `04_015 / 2` ends its shared block with `1F FF` at **0617**, immediately before the English section at **0619**. Handler `C219` compares the operand with the counter held in the immediate byte at `C21B`. For counter 0–254 it branches to `C1E1`, which reloads the checkpoint and yields. For counter 255 it returns and falls into the following language bytes. The exporter records this as a **guarded boundary exit**, not an unconditional stop or a text continuation. Whether this scene can actually reach counter 255 has not been established. The exceptional path remains unanalysed and explicitly visible in both scenario and presentation exports.

## Verification scope

- Original `BE07/BF1A` setup parsing now covers **all 107 world-setup records and 1,857 placements**, including all seven inline blocks, their current-object indices, group boundaries and counted-object totals. The former four exclusions are gone.
- The seven blocks were additionally compared against explicit reference effects in **224 cases**, varying object contents, clock wraparound and model heights. Comparisons cover the full current object and code segment (including globals and modified stream), SI advancement and DS restoration. Original helpers execute without substitution in this differential check.
- A linked check passes the first block's actual patched immediate to the later block on a different object.
- All **256 altitude flag values** and **256 terminal counter values** were executed against the original handlers. The wait check observes entry to the retry helper; it does not run the scheduler.

The full parser check uses synthetic zero-height geometry and a known synthetic player position. Underground route initialisation remains substituted. These checks establish setup effects and byte consumption, not complete mission behaviour, real-world placement height, rendering, or mission completion.

Reproduce with:

```sh
python3 tools/inspect_missions.py
PYTHONPATH=/tmp/darker-python python3 tools/verify_missions.py
PYTHONPATH=/tmp/darker-python python3 tools/verify_mission_native.py
python3 tools/mission_browser.py
python3 tools/extract_presentations.py
```
