Ver Fonte

Restore Ember beam poses and record black-video evidence

Millie há 3 dias atrás
pai
commit
4142e19833

+ 9 - 0
docs/mission-ember-final-corrections.md

@@ -1,5 +1,14 @@
 # 1AU: movie loader, surge audio and escape explosions
 # 1AU: movie loader, surge audio and escape explosions
 
 
+## Playback report after `6540584`
+
+The user confirms immediate ending audio, but the picture stays black with gameplay HUD visible throughout. Both native players reached decoder state 5. STM subsequently stopped and completed after Escape (t=384298–384404); CNN also reached state 5 (t=384750) and completed after Escape (t=385250–385356). This establishes decoding/playback state and skip sequencing, **not visible video**. The archived log is `build/first-encounter-audit/6540584-black-video.log`.
+
+The failed beam inversion from `6540584` has been reverted at the user's request: normal uses `open`, surge uses `close`. Audio remains tied to the surge callback; shutter mechanics are unchanged. The restored mission route and all 24 portable tests pass.
+
+The picture investigation separates CPU extraction (`41D140`), fullscreen UI command production (`132B890` → `1278FF0`, command `1B`), GPU Y/U/V upload (`41D7B0`), and the final video draw (`1159CE0`, global shader index `B4`). Shader `80B35981` is resident in the captured process. The idle UI manager at `(RIP target of 132BD5C) & ~15 = 142F4EE30` has the expected `+1E4 = -1`, `+1EC = 0`. These **post-skip** readings do not identify the during-playback failure; an active picture/command-buffer capture is pending.
+
+
 ## Latest playtest: metadata ready, stream missing
 ## Latest playtest: metadata ready, stream missing
 
 
 The user confirms `13f07ee` no longer freezes, but neither ending plays. The log records movie 1 resources ready and playback submitted at t=256404, decoder state 1 at t=256487, state 7 at t=256527, then failure and resource release at t=256598. The escape trigger and movie dispatch are working; the native decoder never reaches playing state 5.
 The user confirms `13f07ee` no longer freezes, but neither ending plays. The log records movie 1 resources ready and playback submitted at t=256404, decoder state 1 at t=256487, state 7 at t=256527, then failure and resource release at t=256598. The escape trigger and movie dispatch are working; the native decoder never reaches playing state 5.

+ 3 - 3
docs/mission-ember-prerendered-ending.md

@@ -15,7 +15,7 @@ The placement's entity reference is at +0x30. Both entities contain class 808065
 
 
 ## Required residency correction
 ## Required residency correction
 
 
-The installed `4f5c706` bridge froze on its first live STM request: the resource lookup read address 0x8 at `349D2C`. Both movie wrappers and headers were registered but unloaded. The subsequent `bc3e912` loader also failed: its kind-2 request sent the ordinary movie tag down the shared-resource path, leaving a handle at `FFFFFFFF` before a worker dereferenced it at `3374C6`. The current bridge uses the package-verified kind 1 and pins the movie, header, subtitle and shared metadata tags plus the compact video-stream mapping before playback. The `13f07ee` test reached decoder preparation but failed with state 7; it had omitted that stream mapping. Native `3591B0` initializes the media datum without copying the full video into RAM. See [the correction evidence and validation](mission-ember-final-corrections.md). Rendered playback remains unconfirmed until a fresh game test.
+The installed `4f5c706` bridge froze on its first live STM request: the resource lookup read address 0x8 at `349D2C`. Both movie wrappers and headers were registered but unloaded. The subsequent `bc3e912` loader also failed: its kind-2 request sent the ordinary movie tag down the shared-resource path, leaving a handle at `FFFFFFFF` before a worker dereferenced it at `3374C6`. The current bridge uses the package-verified kind 1 and pins the movie, header, subtitle and shared metadata tags plus the compact video-stream mapping before playback. The `13f07ee` test reached decoder preparation but failed with state 7; it had omitted that stream mapping. Native `3591B0` initializes the media datum without copying the full video into RAM. See [the correction evidence and validation](mission-ember-final-corrections.md). The subsequent `6540584` test reaches native playing state with audible sound, but the user reports a permanently black picture and gameplay HUD overlay; presentation remains unresolved.
 
 
 ## Native playback bridge
 ## Native playback bridge
 
 
@@ -27,7 +27,7 @@ Movie requests are ordinary committed mission intents, limited to private missio
 
 
 The decoder's current asset is +0x1B4 and native state is +0x1B0. Rendering in 41D140 is gated on state 5. The bridge requires state 5 for its exact asset before reporting playback, then requires the native busy predicate to clear with stopped/end state 0 or 6 before completion. An error, replaced decoder, changed asset after playback, or changed world fails without completing the mission. Queue/preparation have 30-second bounds; playback has a 600-second bound. These deadlines fail, never award completion.
 The decoder's current asset is +0x1B4 and native state is +0x1B0. Rendering in 41D140 is gated on state 5. The bridge requires state 5 for its exact asset before reporting playback, then requires the native busy predicate to clear with stopped/end state 0 or 6 before completion. An error, replaced decoder, changed asset after playback, or changed world fails without completing the mission. Queue/preparation have 30-second bounds; playback has a 600-second bound. These deadlines fail, never award completion.
 
 
-The movie frame is observed after its original routine, as well as the player-camera frame. This is necessary because movie presentation may stop the player-camera callback. The extra frame poll is active only while this bridge has a request. Foreground Escape invokes the same native stop operation, edge-triggered only during confirmed playback. Direct videos have no type-6 source to emit the existing cinematic-skip incident, so unrelated/stale type-6 incidents are ignored. Completion still waits for the native stopped receipt.
+The native CPU movie-frame routine (`41D140`) is observed after its original routine, as well as the player-camera frame. This routine extracts decoded Y/U/V planes; the separate UI/video renderer submits and draws them. This is necessary because movie presentation may stop the player-camera callback. The extra frame poll is active only while this bridge has a request. Foreground Escape invokes the same native stop operation, edge-triggered only during confirmed playback. Direct videos have no type-6 source to emit the existing cinematic-skip incident, so unrelated/stale type-6 incidents are ignored. Completion still waits for the native stopped receipt.
 
 
 ## Mission ordering
 ## Mission ordering
 
 
@@ -39,4 +39,4 @@ This removes the failing transition from the ending route. General world teardow
 
 
 All 23 portable tests and five Lua mission suites pass. Coverage rejects queue/preparation as completion, wrong assets, decoder errors, stale type-6 incidents, duplicate completion, and mission completion after only the first movie. It also checks that the ending requests no world selection and that native completion following a skip follows the same sequence. All four native signatures and six relative-call targets match the saved executable image.
 All 23 portable tests and five Lua mission suites pass. Coverage rejects queue/preparation as completion, wrong assets, decoder errors, stale type-6 incidents, duplicate completion, and mission completion after only the first movie. It also checks that the ending requests no world selection and that native completion following a skip follows the same sequence. All four native signatures and six relative-call targets match the saved executable image.
 
 
-Live playback, video/audio presentation, both Escape skips and the post-movie mission-complete presentation still require a game test. Diagnostics use `ev=ember_movie` with queued, submitted, decoder, playing, stop_requested and complete, or a specific failure reason.
+Live audio and both Escape skips are confirmed by the `6540584` test, including native completion receipts for both movies. Visible video and the post-movie mission-complete presentation remain unconfirmed; the reported video is black with HUD overlaid. Diagnostics use `ev=ember_movie` with queued, submitted, decoder, playing, stop_requested and complete, or a specific failure reason.

+ 3 - 3
scripts/mission_ember/apex.lua

@@ -69,10 +69,10 @@ return function(m, a, ending)
     -- `ring_device_sense` in the log carries their native position and power.
     -- `ring_device_sense` in the log carries their native position and power.
     local structure_objects = {"SPECOPS_APEX_RING_CORE_OBJECT", "SPECOPS_APEX_RING_RING_OBJECT"}
     local structure_objects = {"SPECOPS_APEX_RING_CORE_OBJECT", "SPECOPS_APEX_RING_RING_OBJECT"}
     local beam_devices = {"SPECOPS_APEX_RING_LASER_DEVICE", "SPECOPS_APEX_RING_RING_DEVICE"}
     local beam_devices = {"SPECOPS_APEX_RING_LASER_DEVICE", "SPECOPS_APEX_RING_RING_DEVICE"}
-    -- The latest live test establishes the beam's poses: close is normal, open is surge.
-    -- Keep this mapping separate from the encounter clock and shutter cooling state.
+    -- Restore the pre-6540584 mapping requested after the failed inversion test:
+    -- normal uses open; the surge uses close. Keep the encounter/audio clock unchanged.
     local function beam_pose(c, surging, snap)
     local function beam_pose(c, surging, snap)
-        for _, name in ipairs(beam_devices) do a.device(c, name, surging, snap) end
+        for _, name in ipairs(beam_devices) do a.device(c, name, not surging, snap) end
     end
     end
     -- Firing: the beam is present and both of its devices are powered.
     -- Firing: the beam is present and both of its devices are powered.
     local function beam(c, s, firing, snap)
     local function beam(c, s, firing, snap)

+ 7 - 7
tests/mission_ember_routes_test.lua

@@ -213,7 +213,7 @@ timer('ember.apex.setup.')
 for _,name in ipairs({'SPECOPS_APEX_RING_LASER_OBJECT','SPECOPS_APEX_RING_RING_OBJECT'}) do
 for _,name in ipairs({'SPECOPS_APEX_RING_LASER_OBJECT','SPECOPS_APEX_RING_RING_OBJECT'}) do
     call(R.dispatch,'object',c,s,event(name,{generation=1,present=true,alive=true}))
     call(R.dispatch,'object',c,s,event(name,{generation=1,present=true,alive=true}))
 end
 end
-assert(transition('SPECOPS_APEX_RING_LASER_DEVICE',true).transition=='close')
+assert(transition('SPECOPS_APEX_RING_LASER_DEVICE',true).transition=='open')
 assert(transition('SPECOPS_APEX_RING_LASER_DEVICE',true).snap==false, 'startup must run effect events instead of seeking past them')
 assert(transition('SPECOPS_APEX_RING_LASER_DEVICE',true).snap==false, 'startup must run effect events instead of seeking past them')
 local primedCalls=#calls
 local primedCalls=#calls
 call(R.dispatch,'object',c,s,event('SPECOPS_APEX_RING_LASER_OBJECT',{generation=1,present=true,alive=true}))
 call(R.dispatch,'object',c,s,event('SPECOPS_APEX_RING_LASER_OBJECT',{generation=1,present=true,alive=true}))
@@ -279,7 +279,7 @@ local beamMoved=false
 for i=beforeAudio+1,#calls do
 for i=beforeAudio+1,#calls do
     local row=calls[i]
     local row=calls[i]
     if row[1]=='transition' and row[2]==slotDefs[m.Slot.SPECOPS_APEX_RING_LASER_DEVICE].name then
     if row[1]=='transition' and row[2]==slotDefs[m.Slot.SPECOPS_APEX_RING_LASER_DEVICE].name then
-        beamMoved=row[3].transition=='open'
+        beamMoved=row[3].transition=='close'
     end
     end
     if row[1]=='play_sequence' then
     if row[1]=='play_sequence' then
         assert(beamMoved,'alarm was requested before the surge state changed')
         assert(beamMoved,'alarm was requested before the surge state changed')
@@ -291,10 +291,10 @@ assert(vars['ember.apex.vent_step']=='warning' and timers['ember.apex.vents.1']=
 -- The weapon fires continuously through the fight; the exposure cycle must not blink it.
 -- The weapon fires continuously through the fight; the exposure cycle must not blink it.
 -- The surge is the authored device drive of a beam that stays present and powered.
 -- The surge is the authored device drive of a beam that stays present and powered.
 assert(vars['ember.apex.beam']==true,'the weapon must keep firing across the cycle')
 assert(vars['ember.apex.beam']==true,'the weapon must keep firing across the cycle')
--- Live-confirmed pose: close is normal; open is surge. Shutter timing stays independent.
+-- Restored pre-6540584 pose: normal is open, surge is close.
 assert(vars['ember.apex.surge']==true,'the warning must drive the beam')
 assert(vars['ember.apex.surge']==true,'the warning must drive the beam')
-assert(transition('SPECOPS_APEX_RING_LASER_DEVICE', true).transition=='open')
-assert(transition('SPECOPS_APEX_RING_RING_DEVICE', true).transition=='open')
+assert(transition('SPECOPS_APEX_RING_LASER_DEVICE', true).transition=='close')
+assert(transition('SPECOPS_APEX_RING_RING_DEVICE', true).transition=='close')
 assert(transition('REACTOR_CLAMSHELL_EAST_DOOR_A_DEVICE').transition=='close')
 assert(transition('REACTOR_CLAMSHELL_EAST_DOOR_A_DEVICE').transition=='close')
 local coolingStart=#calls
 local coolingStart=#calls
 timer('ember.apex.vents.')
 timer('ember.apex.vents.')
@@ -306,7 +306,7 @@ for i=coolingStart+1,#calls do
     local row=calls[i]
     local row=calls[i]
     if row[1]=='transition' then
     if row[1]=='transition' then
         for _,name in ipairs({'SPECOPS_APEX_RING_LASER_DEVICE','SPECOPS_APEX_RING_RING_DEVICE'}) do
         for _,name in ipairs({'SPECOPS_APEX_RING_LASER_DEVICE','SPECOPS_APEX_RING_RING_DEVICE'}) do
-            if row[2]==slotDefs[m.Slot[name]].name and row[3].transition=='close' then restored[name]=true end
+            if row[2]==slotDefs[m.Slot[name]].name and row[3].transition=='open' then restored[name]=true end
         end
         end
         if row[2]==slotDefs[m.Slot.REACTOR_CLAMSHELL_EAST_DOOR_A_DEVICE].name and row[3].transition=='open' then
         if row[2]==slotDefs[m.Slot.REACTOR_CLAMSHELL_EAST_DOOR_A_DEVICE].name and row[3].transition=='open' then
             assert(restored.SPECOPS_APEX_RING_LASER_DEVICE and restored.SPECOPS_APEX_RING_RING_DEVICE,
             assert(restored.SPECOPS_APEX_RING_LASER_DEVICE and restored.SPECOPS_APEX_RING_RING_DEVICE,
@@ -427,7 +427,7 @@ assert(#calls==afterRail,'duplicate hazard callback must not reattach scorch')
 -- ring objects would take the beam and its surrounding structure out of the world entirely.
 -- ring objects would take the beam and its surrounding structure out of the world entirely.
 assert(vars['ember.apex.beam']==false,'the beam must stop firing after the deposit')
 assert(vars['ember.apex.beam']==false,'the beam must stop firing after the deposit')
 assert(vars['ember.apex.surge']==false,'the drive must return to its baseline with the power')
 assert(vars['ember.apex.surge']==false,'the drive must return to its baseline with the power')
-assert(transition('SPECOPS_APEX_RING_LASER_DEVICE', true).transition=='close',
+assert(transition('SPECOPS_APEX_RING_LASER_DEVICE', true).transition=='open',
     'a dark weapon rests in its normal pose, not the surge')
     'a dark weapon rests in its normal pose, not the surge')
 local poweredOff=false
 local poweredOff=false
 for _,row in ipairs(calls)do
 for _,row in ipairs(calls)do