DARKER Research archive

Object update order and late-frame context switches

The native list walker now runs with controlled multi-object scripts. This establishes traversal and activation timing without substituting a guessed object scheduler. It does not yet execute a complete mission or all movement callbacks.

Main-loop order

The main path calls 784D at 3E05; that routine reaches 797B at 78E9. The category walker performs:

Order List header Evidence
1 6FD0, player/craft list 7986–7989
2 6FD8, air list 79A3–79A6
3 6FC8, ground list 79A9–79AC
— player weapon update C8E9 79AF
4 6FB8 79B2–79B5
5 6FC0 79B8 falls into walker

Each list follows its head and object +0 links. Before invoking object callback +66 at 7A2D, it copies current X/Y/height to +38/+3A/+3C and supplies the step value from 7A2B in CX. Lifecycle flags can divert objects into removal/recycling paths; those paths are not exercised in this fixture. Static list 6FB0 is not traversed by this particular routine.

After these callbacks, the main path handles targeting/input, calls C510 and then runs the player's mission interpreter BF97 at 3E2D. C510 supplies BX from BF0. The air scheduler gateway 8AA1 also loads BF0 before BF97. These comparison-clock reads differ from BF8 used by several deadline producers; pause/clock relationships remain to be established.

The fixture uses 8AA1 as a synthetic callback for test objects in each list. That proves how script effects interact with native traversal, not that every real object's callback invokes the main script interpreter. Ground vehicles also have their separate compact-route machinery.

Controlled two-update activation traces

Activator Reserve activated First eligible callback traversal
Air object Ground Later in the same update
Air object Air Next update
Player mission script after the walker Ground Next update

C386 prepends activated objects to the active list. The walker at 7A30 then reads the current object's next link, rather than restarting from the head. An object prepended to the list already being traversed is therefore not visited on that pass. A later list's head has not yet been read, so that activation is visible immediately.

Each result was checked over two executions of the original 797B/79BB walker with the original activation handlers and interpreter. Two calls use the same clock deliberately: these checks concern traversal eligibility, not elapsed physics time or a measured frame rate.

Owner registration and the late context gate

Opcode 24 registers the current object in 3E8C, saves the previous registration in object +5A and stops its script, as documented in reserve/context analysis.

The main path eventually reaches 3E83, after the player mission interpreter and the intervening presentation/render calls. The native gate:

Here C77E exchanges the saved script/message context and sets the player deadline, then returns to 3E96, not to the interpreter. Incoming script execution is deferred until a subsequent interpreter invocation. In contrast, opcode 26 is dispatched from BFA9 and returns there, immediately continuing in the incoming script.

The four combinations of owner absent/present and flag zero/FF execute the actual gate in the fixture. Neither the gate nor C77E clears 3E8C. C77E complements the flag, so an incoming zero flag becomes FF and prevents the same gate firing again until another path changes it.

A detail still requiring care: C77E saves incoming SI as the alternate continuation. In the opcode path this is naturally the byte after opcode 26. At the late-frame call site, SI comes from preceding main-loop work. The isolated test uses an explicit sentinel SI and checks that it is saved unchanged; it does not claim that sentinel represents a real mission continuation. Separately, C776 loads SI from object +58 before joining the common exchange at C781. These entry paths must not be collapsed into an assumed single high-level coroutine operation until their caller contracts are fully traced.

Reproduction and limits

PYTHONPATH=/tmp/darker-python python3 tools/verify_mission_update_order.py

Trace export includes native callback order, three two-update activation traces and four late-frame gate checks. Physics after 8AA8 and player weapon update C8E9 are intercepted. The player interpreter call is supplied separately with the clock register C510 provides. No rendering, collision, list removal or actual mission completion is simulated.

Next: trace the alternate C776 entry and the late-frame SI contract, identify how each real callback schedules its script or route, then include object completion/removal and shared text in a selected real mission trace.

Follow-up: setup callback census and geometry context entry identify real main-script versus compact-route callbacks and verify the C776 entry contract. The late-frame saved-SI lifecycle remains unresolved.