Fix AE001H spritesheet animation
This commit is contained in:
@@ -840,8 +840,8 @@ annotated in Ghidra, saved.
|
||||
|---|---|---|
|
||||
| `0x22f` | `gfx_op_0x22f_set_position_anim` → `gfx_worker_set_translation` | set object **position** (translation vec `obj+0x5d4`); base transform, not a ping-pong channel |
|
||||
| `0x229` | `gfx_op_0x229_set_position` (`FUN_00472bb0`+`FUN_00472be0`) | set object **position/geometry** immediately (`obj+0x420/0x424` + vec `obj+0x440..0x448`) |
|
||||
| `0x239` | `gfx_op_0x239_set_srcrect_cell` → `gfx_worker_set_srcrect_cell` | set **spritesheet** grid `obj+0x238/0x23c` + static cell `obj+0x234` |
|
||||
| `0x231` | `gfx_op_0x231_anim_srcrect` → `gfx_worker_anim_srcrect` | **animate spritesheet cell**: bit2 active, period `obj+0x230`, grid `obj+0x238/0x23c` → interpolator SRC-RECT SCROLL channel (ping-pong across the row) |
|
||||
| `0x239` | `gfx_op_0x239_set_srcrect_cell` → `gfx_worker_set_srcrect_cell` | one-shot **spritesheet-cell** channel: delay/duration `obj+0x48/+0x5c`, total frames/columns `obj+0x238/+0x23c`, target frame `obj+0x234` |
|
||||
| `0x231` | `gfx_op_0x231_anim_srcrect` → `gfx_worker_anim_srcrect` | looping **spritesheet-cell** channel: milliseconds per frame `obj+0x230`, total frames `obj+0x238`, columns `obj+0x23c`; row-major and wraps, not ping-pong |
|
||||
| `0x232` | `gfx_op_0x232_anim_color` → `gfx_worker_anim_color` | **animate color** (pulsing GLOW): bit2 active, period `obj+0x220`, target `obj+0x240` → interpolator COLOR channel (ping-pong). Distinct from static `0x202`/`0x203` (`obj+0x60/0x64`) |
|
||||
| `0x228` | `gfx_op_0x228_query_position` (`FUN_0047cdd0`) | **query** current computed (x,y,z) → operand slots 3/4/5 (script logic, not render) |
|
||||
| `0x23f` | `gfx_op_0x23f_query_object` (`FUN_0042a520`) | **query** an object status/value → operand slot 1 |
|
||||
@@ -879,6 +879,13 @@ while `0x21c` is parked completes only the active foreground surface transition
|
||||
not pre-arm the following `wait-for-input`, and it does not complete independent retained rotation,
|
||||
matrix, spritesheet, or color-animation channels.
|
||||
|
||||
**Source-rectangle correction (2026-07-11):** `gfx_object_anim_interpolate` preserves the source rectangle
|
||||
set by `draw-texture`; `0x231` does not divide that rectangle by its operands. It computes
|
||||
`frame = floor(elapsed / frame_period) % frame_count`, then offsets both X bounds by
|
||||
`rect_width * (frame % columns)` and both Y bounds by `rect_height * (frame / columns)`. SC0000 passes
|
||||
`(100, 8, 4)` for AE001H: eight 200x200 cells in an 800x400, 4x2 sheet. Treating 8 and 4 as grid width
|
||||
and height shrank the crop to 25x50 and made the intended cave spirit effectively disappear.
|
||||
|
||||
**Resolved 2026-07-11:** `0x236` is the movie-to-retained-surface path described below. The unclassified
|
||||
`0x242/0x23d/0x20a/0x20e` tail (2-arg flags / inline) remains GAP and outside this slice.
|
||||
|
||||
|
||||
@@ -271,8 +271,9 @@ Native handler gfx_op_0x20c_present_frame -> gfx_render_frame @0x4820b0. This is
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x231 `u00421EA0` (u00421EA0, argc 4)
|
||||
- **summary:** 0x231 anim-srcrect (handle)(period)(gridW)(gridH): ping-pong the spritesheet cell across the grid over period ms. Worker gfx_worker_anim_srcrect @0x47eec0 -> interpolator SRC-RECT SCROLL channel. C# VM: GfxState.SetSrcRect. See docs/engine-re.md §SC0000 anim cluster.
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
- **summary:** (handle)(frame_period_ms)(frame_count)(column_count) — loop row-major through the spritesheet. Every frame preserves draw-texture's source-rectangle width/height; frame=floor(elapsed/frame_period)%frame_count, src offset=(frame%columns*width, frame/columns*height). Worker gfx_worker_anim_srcrect @0x47eec0; consumer gfx_object_anim_interpolate @0x473ed0.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Native /v2 decompile: worker stores period at obj+0x230, frame_count at +0x238, columns at +0x23c. Interpolator computes ((now-start)/period)%frame_count, then offsets both source-rect X bounds by rect_width*(frame%columns) and Y bounds by rect_height*(frame/columns). SC0000 uses (100,8,4) with AE001H's eight 200x200 cells in a 4x2 800x400 sheet.
|
||||
|
||||
### 0x232 `u00421EF0` (u00421EF0, argc 4)
|
||||
- **summary:** 0x232 anim-color (handle)(period)(alpha)(color): ping-pong the object color/alpha toward the packed target over period ms (pulsing GLOW). Worker gfx_worker_anim_color @0x47ef50 -> interpolator COLOR channel. C# VM: GfxState.SetColorAnim. See docs/engine-re.md §SC0000 anim cluster.
|
||||
@@ -295,8 +296,9 @@ The handler requires an existing destination texture, allocates/reuses a 0x478-b
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
|
||||
### 0x239 `u004223C0` (u004223C0, argc 6)
|
||||
- **summary:** 0x239 set-srcrect-cell (handle)(p3)(p4)(gridW)(gridH)(cell): set the spritesheet grid + static visible cell. Worker gfx_worker_set_srcrect_cell @0x47ed90. C# VM: GfxState.SetSrcRect (period 0). See docs/engine-re.md §SC0000 anim cluster.
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
- **summary:** (handle)(delay_ms)(duration_ms)(frame_count)(column_count)(target_frame) — one-shot row-major source-rectangle cell channel. Worker gfx_worker_set_srcrect_cell @0x47ed90 stores timing at obj+0x48/+0x5c, layout at +0x238/+0x23c, and target at +0x234. C# currently retains the endpoint cell immediately.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Native /v2 worker and gfx_object_apply_transform_channels decompile. The consumer advances target_frame cells over duration after delay, preserves the existing source-rect dimensions, and commits the endpoint.
|
||||
|
||||
### 0x23f `u00422930` (u00422930, argc 2)
|
||||
- **summary:** 0x23f query-object (out)(handle): return object status (FUN_0042a520; -1 if none). C# VM: 0 if the object exists else -1. See docs/engine-re.md §SC0000 anim cluster.
|
||||
|
||||
@@ -646,7 +646,7 @@ plan `.../plans/2026-07-08-sc0000-anim-transform-cluster.md`, branch `feat/anim-
|
||||
**Built (hybrid: engine resolves, host blits):**
|
||||
- `GfxObject` gains src-rect (spritesheet) + animated-color channels; `GfxState.SetSrcRect` / `SetColorAnim`;
|
||||
`BlendMath.PingPong`; `SnapshotVisibleObjects(long nowMs)` = a port of `gfx_object_anim_interpolate`
|
||||
(ping-pong the spritesheet cell + color/glow), driven by the **`FrameClock`** (the "mach 5" pacing fix).
|
||||
(looping row-major spritesheet cells + ping-pong color/glow), driven by the **`FrameClock`** (the "mach 5" pacing fix).
|
||||
- Wired 7 ops: `0x22f`/`0x229` position (direct V24 set), `0x239`/`0x231` spritesheet (static cell / animate),
|
||||
`0x232` color glow (ping-pong), `0x228`/`0x23f` queries (geometry back to script vars).
|
||||
|
||||
@@ -1380,5 +1380,16 @@ distinct from `0x21e`'s one-shot target. SC0000 scales the two AE001D circles to
|
||||
them at 100%, almost entirely below the viewport. `GfxState.SetCurrentScale` and VM dispatch now reproduce
|
||||
the native matrices, with focused geometry/dispatch tests. Validation: engine **145/145**, opcode build/lint,
|
||||
Godot build/capture, Ghidra annotations saved, and user confirmation that the CG and animated glow are both
|
||||
visible. This AE001D path is a retained scaled/rotating texture; later missing `0x231` spritesheet-cell
|
||||
effects remain separately scoped.
|
||||
visible. This AE001D path is a retained scaled/rotating texture; the later `0x231` spritesheet-cell issue
|
||||
was separately resolved by preserving draw-texture's 200x200 cell and interpreting `(8,4)` as total
|
||||
frames/columns rather than a grid divisor.
|
||||
|
||||
### A2b -- SC0000 post-movie AE001H spritesheet correction ✅ DONE (2026-07-11)
|
||||
|
||||
The reported missing cave spirit was the `0x231` path, independent of the earlier AE001D retained glow.
|
||||
Native interpolation proved `(period, 8, 4)` means milliseconds per frame, total frames, and columns;
|
||||
the existing 200x200 draw-texture rectangle is one cell and must not be divided again. The retained model
|
||||
now cycles the eight AE001H cells row-major and wraps. Focused tests cover the exact 800x400/4x2 layout.
|
||||
Validation: engine **146/146**, opcode sources regenerated, Godot zero-warning build and threaded selftest,
|
||||
real-scene compositor trace across all eight cells, Ghidra `/v2` annotations saved, and user confirmation
|
||||
on the normal client path. The automated-shot wrong-CG state remains the pre-existing separate gotcha.
|
||||
|
||||
Reference in New Issue
Block a user