fix(gfx): restore third CG glow
This commit is contained in:
@@ -695,7 +695,10 @@ per-frame bytecode. Reversed + annotated in Ghidra:
|
||||
`obj+0x214`, period `obj+0x228`, and axis `obj+0x244/248/24c`.
|
||||
- **`gfx_object_set_rotation_cycle`** (`0x47f060`, worker for legacy op **`0x234`**)
|
||||
configures that channel. `gfx_object_anim_interpolate` consumes it from frame-time `ctx+0xb550`
|
||||
as a repeating 0..360-degree axis rotation. Op **`0x1fd`** is a separate scaled 3-vector setter.
|
||||
as a repeating 0..360-degree axis rotation. Op **`0x1fd`**
|
||||
(`gfx_op_0x1fd_set_vec_scaled@0x422650` → `gfx_object_set_scale_current@0x47e6b0`) is an immediate
|
||||
current-scale setter: it divides integer X/Y/Z percentages by 100, marks scale state at `obj+0x68`, and
|
||||
writes `matrix4_make_scale` at `obj+0x6c`.
|
||||
- **Op `0x238`** (`gfx_op_0x238_set_anim_clock`) sets a **global animation clock**, **non-blocking**:
|
||||
`ctx+0x51b78 = 0` (elapsed), `ctx+0x51b7c = duration` (the max per-object duration; SC0000 `label_1235a`
|
||||
maxes a table to compute it). It does **not** loop/wait.
|
||||
@@ -763,7 +766,28 @@ Ghidra functions renamed + plate-commented, saved).
|
||||
`SRCALPHA/INVSRCALPHA`, 2/3 additive/special for glow/flash) and passes a modulation color/alpha to the
|
||||
device draw. Slice A ports the **alpha** path (fades); additive (glow) is deferred (its `local_2c` source
|
||||
field is `obj+0x30`, the value written by op `0x203`. Mode 1 uses packed ARGB alpha as opacity and RGB
|
||||
as multiplicative D3D modulation. Modes 2/3 remain separately scoped beyond the completed mode-1 path.
|
||||
as multiplicative D3D modulation. For a **textured mode-0** object, preserved `0xffffffff` is opaque
|
||||
identity, not a request to replace the texture with white; the packed alpha byte is therefore not a
|
||||
generic tint-strength control. Modes 2/3 remain separately scoped beyond the completed mode-1 path, and
|
||||
surfaceless mode-0 fills remain a distinct consumer case.
|
||||
|
||||
**SC0000 third-CG white-screen and missing-glow fix (2026-07-11).** The page containing
|
||||
`大役を担ったのは…` reaches the intended EV052DA image and both animated AE001D layers. A synchronized
|
||||
Godot capture proved AE001D is correctly alpha-bearing and drawn in mode 1 at only 6-8% object opacity;
|
||||
it was not the white wall. During the preceding `0x223` EV052CA→EV052DA crossfade, base handle `0xcb2a`
|
||||
renders EV052DA in mode 2 with identity modulation. When the transition ends, `0x203@0x12478` restores that
|
||||
same textured object to mode 0 with negative color operands, preserving `0xffffffff`. Native keeps EV052DA
|
||||
visible; the old port resolved the state as `tintStr=1.00` and lerped every source texel to white. Textured
|
||||
mode 0 now resolves as opaque multiplicative RGB, making white identity, while surfaceless mode-0 fill
|
||||
strength remains separate.
|
||||
|
||||
The first corrected capture exposed a second independent gap: AE001D was submitted and rotating but had no
|
||||
visible pixel contribution. Its 800×800 circle was based at `(0,550)` around anchor `(400,950)` and remained
|
||||
at the port's default 100% scale, almost wholly below the viewport. SC0000 executes `0x1fd` with
|
||||
`210/210/100` and `240/240/100`; implementing the native immediate current-scale setter expands the circles
|
||||
into the viewport (the first top edge reaches y=110). The user positively confirmed both the restored CG and
|
||||
visible glow on the ordinary interactive path. This glow is a retained scaled/rotating texture, not an
|
||||
`0x231` spritesheet-cell animation; later missing spritesheet effects remain a separate issue.
|
||||
|
||||
**Interpolation RE pass (2026-07-08, stalled → both deferrals confirmed).** Attempted to pin how a `0x202`
|
||||
fade animates so smooth ramping could join slice A. Findings (Ghidra `gfx_object_anim_interpolate`
|
||||
|
||||
@@ -151,6 +151,11 @@ SC0000 label_1235a reaches this when 0x1c7/0x1cc are zero. Native run-state bit
|
||||
- **grounding:** source=investigation, confidence=med
|
||||
- **evidence:** SC0000 CG-load subroutine label_12649: `draw-texture (ptr) (slot) 0 0 (w) (h) (dstx) (dsty)`; full-screen slot-3 draws use 0x320x0x258 (800x600).
|
||||
|
||||
### 0x1fd `gfx-set-scale-current` (u00420620, argc 4)
|
||||
- **summary:** (handle)(scale_x_percent)(scale_y_percent)(scale_z_percent) — immediately replace the retained object's current scale matrix at obj+0x6c. The handler divides each integer operand by 100.0 before calling matrix4_make_scale; this is distinct from 0x21e's delayed one-shot target scale.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: handler gfx_op_0x1fd_set_vec_scaled@0x422650 fetches operands 2..4, divides each by the 100.0 constant, and calls gfx_object_set_scale_current@0x47e6b0. The worker gets/creates the object, marks obj+0x68, and calls matrix4_make_scale on obj+0x6c. SC0000 sets AE001D handles to 210/210/100 and 240/240/100; without this setter their 800x800 alpha circles remain below the viewport. Both functions annotated and /v2 saved 2026-07-11.
|
||||
|
||||
### 0x1ff `set-gfx-geom3-c` (set-gfx-geom3-c, argc 4)
|
||||
- **summary:** 0x1ff (handle)(a)(b)(c) — gfx cmd-type 9. Handler gfx_op_0x1ff_set_geom3 @0x4227b0: SETS a 3-vector (int→float a,b,c) on object `handle` via native worker FUN_0047e800 (sibling of 0x217/0x219, a distinct per-object vector). See docs/engine-re.md gfx op-contract table.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
@@ -162,9 +167,9 @@ SC0000 label_1235a reaches this when 0x1c7/0x1cc are zero. Native run-state bit
|
||||
- **evidence:** Ghidra handler 0x4228d0 packs operands 4/5 and calls worker 0x47ea00(handle,delay,duration,packed). Consumer 0x472f00: shared start +0x34; color delay/duration +0x38/+0x4c; current/target +0x60/+0x64; frame clock ctx+0xb550; bytewise integer LERP; natural or ctx+0xb55c forced completion. /v2 annotated and saved 2026-07-10.
|
||||
|
||||
### 0x203 `gfx-draw-color` (gfx-draw-color, argc 4)
|
||||
- **summary:** 0x203 (handle)(mode)(alpha)(color) — gfx cmd-type 9. Worker stores the D3D blend selector at obj+0x30 and STATIC packed color at obj+0x60. Negative alpha/RGB preserve current static bytes. Mode 0 retains established opaque CG/tint/fill behavior; mode 1 is SRCALPHA/INVSRCALPHA with ARGB alpha opacity and multiplicative RGB modulation; mode 2 is the 0x223 transition-source identity path.
|
||||
- **summary:** 0x203 (handle)(mode)(alpha)(color) — gfx cmd-type 9. Worker stores the D3D blend selector at obj+0x30 and STATIC packed color at obj+0x60. Negative alpha/RGB preserve current static bytes. Mode 0 is the opaque textured path: preserved 0xffffffff is identity (the alpha byte is not tint strength); mode 1 is SRCALPHA/INVSRCALPHA with ARGB alpha opacity and multiplicative RGB modulation; mode 2 is the 0x223 transition-source identity path. Surfaceless mode-0 fill consumption remains a distinct case.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra handler 0x4229a0; negative operands read current obj+0x60, then worker 0x47e9b0 stores op2 at obj+0x30 and ARGB at +0x60. gfx_object_composite call-site 0x47f78f passes +0x30/+0x60 directly to gfx_object_blit_d3d9; mode 1 sets D3DRS SRCALPHA/INVSRCALPHA and the packed color is the device draw modulation. Mode 2 transition setup and synchronized pixels prove 0xffffffff is identity, not solid white.
|
||||
- **evidence:** Ghidra handler 0x4229a0; negative operands read current obj+0x60, then worker 0x47e9b0 stores op2 at obj+0x30 and ARGB at +0x60. gfx_object_composite call-site 0x47f78f passes +0x30/+0x60 directly to gfx_object_blit_d3d9; mode 1 sets D3DRS SRCALPHA/INVSRCALPHA and the packed color is the device draw modulation. Mode 2 transition setup and synchronized pixels prove 0xffffffff is identity, not solid white. SC0000 page 14 adds the mode-0 endpoint proof: after the EV052CA->EV052DA 0x223 crossfade, 0x203@0x12478 restores the base CG to mode 0 with preserved 0xffffffff; native keeps EV052DA visible while the port's tint-strength interpretation turns every texel white.
|
||||
|
||||
### 0x208 `get-texture-size` (get-texture-size, argc 3)
|
||||
- **summary:** 0x208 (slot)(out_w)(out_h) — writes the loaded texture's width/height into two output globals; keystone for bytecode-computed sprite/bg geometry (SC0000 label_12649)
|
||||
@@ -989,10 +994,6 @@ op 0x90 (u0041BEB0, argc 7): `0x90 x y w h tgt_a tgt_b tgt_c`. Kelebek left it "
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x1fd `u00420620` (u00420620, argc 4)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x1fe `u004206C0` (u004206C0, argc 5)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
@@ -1362,3 +1362,23 @@ may add a fully opaque/unmodulated row-copy path as optional incremental work.
|
||||
**Manual validation:** the user tested the ordinary interactive path—the path whose CG state and fade
|
||||
cadence differ from the console capture—and reported a **massive improvement**. This confirms the identity
|
||||
blit/fill fast path materially improves real fade responsiveness, not merely the isolated kernel benchmark.
|
||||
|
||||
### SC0000 third-CG white screen and AE001D glow fixed (2026-07-11)
|
||||
|
||||
The page-14 screenshot path reproduced the user's all-white EV052DA page exactly. Synchronized compositor
|
||||
and opcode evidence excluded the animated glow assets as the white owner: both AE001D layers load
|
||||
successfully, retain their AGF alpha, rotate, and render in mode 1 at 6-8% opacity. Base handle `0xcb2a`
|
||||
was correct through the
|
||||
`0x223` EV052CA→EV052DA transition (`mode=2`, identity), then `0x203@0x12478` restores it to textured mode 0
|
||||
with preserved `0xffffffff`. The old port resolved that endpoint as `tintStr=1.00`, whitening every EV052DA
|
||||
pixel. Textured mode 0 now uses opaque multiplicative RGB modulation, while surfaceless mode-0 fills retain
|
||||
their existing strength behavior. The transition cleanup regression covers mode 2 → mode 0 `(-1,-1)`.
|
||||
|
||||
The resulting non-white capture then proved the glow itself still contributed no visible pixels. Native RE
|
||||
closed the causal gap: `0x1fd(handle,x%,y%,z%)` immediately writes the current scale matrix at `obj+0x6c`,
|
||||
distinct from `0x21e`'s one-shot target. SC0000 scales the two AE001D circles to 210% and 240%; the stub left
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user