Implement AGE text line spacing
This commit is contained in:
@@ -16,6 +16,7 @@ Struct `EngineCtx`, size `0xa1000`. Applied to the Ghidra `/v2` image (dispatch-
|
||||
| `0xb558` | `gfx_dirty_a` | `int` | gfx dirty flag (anim set raises) |
|
||||
| `0xb560` | `gfx_dirty_b` | `int` | gfx dirty flag |
|
||||
| `0x14d54` | `gfx_obj_ptr_table` | `void*` | per-object pointer table (ops 0x212/0x213 write obj+0x64/0x68/0x6c) |
|
||||
| `0x14ea0` | `text_line_spacing` | `int` | extra pixel leading between text lines; defaults to 6, op 0x8b writes it |
|
||||
| `0x14f45` | `script_frame_index` | `int` | call-script frame index (0x1e-dword frames) |
|
||||
| `0x46d14` | `query_table_46d14` | `void*` | stride-0x14 table read by op 0x216 |
|
||||
| `0x51b64` | `frame_timer` | `int` | frame timer (present updates 0x51b64/0x51b68) |
|
||||
|
||||
@@ -1700,6 +1700,31 @@ inventing unsigned behavior. `/v2` names/comments this mount/load/open chain and
|
||||
|
||||
---
|
||||
|
||||
### ADV text line spacing -- opcode `0x8b` (2026-07-19)
|
||||
|
||||
`op_0x8b_set_text_line_spacing@0x41f270` stores its single operand at ADV text-manager offset
|
||||
`+0x560`, or `EngineCtx.text_line_spacing` (`ctx+0x14ea0`). This is pixel leading, not a font face,
|
||||
weight, or effect selector. `adv_text_manager_initialize@0x456800` gives it a native default of 6.
|
||||
|
||||
The horizontal line-break path (`adv_text_append_line_break_horizontal@0x456fd0`) and retained History
|
||||
renderer (`text_history_render_records@0x452970`) pass `manager+0x560 - manager+0x4cc` as the line
|
||||
advance. Offset `+0x4cc` is the primary `LOGFONT.lfHeight`, which AGE stores as a negative pixel height,
|
||||
so the effective pitch is `font pixel height + text_line_spacing`. The corresponding vertical-writing
|
||||
path uses the same pitch to move to the next column. Corpus values support that interpretation: scripts
|
||||
pair 8 pixels with 22/24-pixel Mincho text and 9 pixels with 16-pixel Gothic text.
|
||||
|
||||
History records do not snapshot the `+0x560` field. `text_history_append_text_record@0x456000` retains
|
||||
font, color, effect, geometry, flags, and string state, while `text_history_render_records` reads the
|
||||
manager's current line spacing when it encounters a retained line-break marker. The port therefore keeps
|
||||
line spacing in the current ADV style manager and overrides a History render batch with that current value;
|
||||
the individual record continues to supply its retained font/color/effect fields.
|
||||
|
||||
The `/v2` image names/comments the handler, manager initializer, horizontal/vertical line-break paths, and
|
||||
their low-level cursor-advance helpers. The regenerated 58-field `EngineCtx` is applied and the program is
|
||||
saved.
|
||||
|
||||
---
|
||||
|
||||
## Native walls backlog (targets for this loop)
|
||||
|
||||
- ~~**call-script dispatch**~~ — **SOLVED** (above): `call-script <id>` = raw SYS4INI file index.
|
||||
|
||||
@@ -55,6 +55,11 @@
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x85_handler@0x4163d0 calls text_history_clear@0x455d70 on the text manager. The worker destroys the 0x48-byte record vector and clears the 8-byte logical index vector. Corpus: two sites in each of 143 normal ADV scripts bracket the retained backlog lifetime.
|
||||
|
||||
### 0x8b `set-text-line-spacing` (u0041B3D0, argc 1)
|
||||
- **summary:** (pixels) - set the extra pixel spacing added between text lines.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x8b_set_text_line_spacing@0x41f270 stores operand 1 at text manager +0x560 (ctx+0x14ea0). adv_text_manager_initialize@0x456800 defaults it to 6. Horizontal newline/history paths at 0x456fd0/0x452970 advance y by (+0x560 - primary LOGFONT.lfHeight); lfHeight is negative, so this is font pixel height plus configured leading. Corpus arguments are 8 for 22/24px Mincho blocks and 9 for 16px Gothic blocks.
|
||||
|
||||
### 0x197 `set-ruby-font-size` (set-ruby-font-size, argc 1)
|
||||
- **summary:** (pixels) - set the secondary/ruby text font height and rebuild its native rasterization state.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
@@ -815,10 +820,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
|
||||
|
||||
### 0x8b `u0041B3D0` (u0041B3D0, argc 1)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x8c `jmp` (jmp, argc 1)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=med
|
||||
|
||||
@@ -1899,3 +1899,30 @@ gap. Keep `0x1cb` deferred, and treat `0x1ce`/`0x20a` together as their own spri
|
||||
|
||||
Validation: all 205 engine tests pass, opcode and EngineCtx tests/lints are clean, vm0 RECOVER passes, the
|
||||
Godot build has zero warnings, and threaded `SELFTEST OK`.
|
||||
|
||||
### ADV History text line spacing implemented (2026-07-19)
|
||||
|
||||
Native RE resolves the two remaining `0x8b` calls as text-manager line leading. The handler writes its
|
||||
single pixel count to manager offset `+0x560` (`EngineCtx+0x14ea0`), whose initializer default is 6.
|
||||
Horizontal newline and History rendering add that value to the primary font's positive pixel height; the
|
||||
script's concrete style blocks use 8 pixels with their 22/24-pixel Mincho fonts and 9 with a 16-pixel
|
||||
Gothic font.
|
||||
|
||||
The VM now retains that current style property, Godot applies it as the Label `line_spacing` theme
|
||||
constant, and History rendering matches native ownership: line spacing comes from the text manager's
|
||||
current state rather than from the retained record. A focused regression distinguishes a record retained
|
||||
with spacing 9 from the current History spacing 8, and the real HISTORY route requires all non-empty rows
|
||||
to render with its setup value of 8.
|
||||
|
||||
The canonical opcode and EngineCtx sources are regenerated. The `/v2` handler and all supporting
|
||||
initializer/line-advance functions are named and commented, the expanded 58-field `EngineCtx` is reapplied,
|
||||
and the program is saved. HISTORY is now 75/78 distinct opcodes and 851/854 instructions handled or
|
||||
safe-noop. The remaining instructions are paired sprite-animation service ops `0x1ce`/`0x20a` and the
|
||||
deferred Read-message Skip setting getter `0x1cb`.
|
||||
|
||||
**Next:** investigate and implement `0x1ce`/`0x20a` together as the final non-persistence History support
|
||||
slice. Keep `0x1cb` deferred until the global save/profile storage boundary is chosen.
|
||||
|
||||
Validation: all 205 engine tests pass, including four focused History presentation cases; opcode and
|
||||
EngineCtx tests/lints are clean, vm0 RECOVER passes, the Godot build has zero warnings, and threaded
|
||||
`SELFTEST OK`.
|
||||
|
||||
Reference in New Issue
Block a user