187 lines
No EOL
8.6 KiB
Markdown
187 lines
No EOL
8.6 KiB
Markdown
# Editor-Item Animation In Retail Crusader And The Viewer
|
|
|
|
This note closes the current map-viewer animation lane for editor/helper objects that flash, cycle colors, or step through multiple frames.
|
|
|
|
The key result is that two different animation systems overlap in this lane:
|
|
|
|
- frame animation from Crusader `TYPEFLAG.DAT`
|
|
- palette-slot animation from the shared `CycleProcess` rows written into palette entries `8..14`
|
|
|
|
The viewer now reproduces both, with one important caveat:
|
|
|
|
- the frame-selection semantics are evidence-backed, but the exact retail wall-clock tick length is still not directly closed from the live DOS executable, so the viewer uses the recovered `animType/animData/animSpeed` rules with a viewer-side step cadence that stays in family with the already-recovered palette cycle
|
|
|
|
## Short Answer
|
|
|
|
The flashing editor walls and helper surfaces are not a separate editor-only special effect process.
|
|
|
|
Current best model:
|
|
|
|
1. many editor/helper shapes are tagged `SI_TRANSL` and use the low Crusader translucent xform slots
|
|
2. those low slots map heavily to source palette indices `8..14`
|
|
3. `CycleProcess_Update` advances those same palette rows globally
|
|
4. when editor/helper sprites use those slots, they inherit the flashing/cycling colors automatically
|
|
5. some shapes also have nonzero `animType`, so they change frame as well as color
|
|
|
|
## Evidence Base
|
|
|
|
### Live `CRUSADER.EXE` / Ghidra side
|
|
|
|
- `CycleProcess_Update` at `1438:011b` advances the shared palette-cycle rows and writes them back through `SuperVGA_SetPaletteColor` at `1438:0366`
|
|
- the same recovered cycle rows already explained the F7-family overlay colors in [docs/f7-overlays.md](docs/f7-overlays.md)
|
|
- `Gamepal_InitXformpalDatStruct` / `Gamepal_LoadXformpalDat` / `Gamepal_ReadXformpal_1028_0348` at `1028:01db`, `1028:0250`, and `1028:0348` are the live xform-palette load path
|
|
- `ItemType_LoadTypeflagDat` / `Item_GetTypeflagData` at `10f8:0275` / `10f8:0336` are the live typeflag load/access anchors for the 9-byte Crusader `TYPEFLAG.DAT` rows
|
|
- `Item_PaintSprite` at `1198:02e4` still skips `SI_EDITOR` in the normal gameplay renderer, so most of this animation is normally only visible on debug/editor/helper lanes unless another overlay or engine-side viewer exposes those objects
|
|
|
|
### Renderer-side direct pixel evidence
|
|
|
|
The earlier translucency pass already established that representative editor/helper translucent shapes are dominated by source palette slots `8`, `9`, `10`, `11`, `13`, and sometimes `14`.
|
|
|
|
Representative probe families:
|
|
|
|
- invisible/editor walls `0x005A..0x0069`
|
|
- helper `0x00E9`
|
|
- `Zappy_Surface_*` `0x044D` / `0x044E`
|
|
|
|
That evidence is recorded in [docs/map_renderer/translucency-xformpal.md](translucency-xformpal.md).
|
|
|
|
### Open-source Crusader engine cross-check
|
|
|
|
The missing frame-animation semantics are closed well enough by the Crusader-specific loaders in ScummVM and Pentagram:
|
|
|
|
- Crusader `TYPEFLAG.DAT` is a 9-byte format
|
|
- byte `4` high nibble = `animType`
|
|
- byte `5` low nibble = `animData`
|
|
- byte `5` high nibble = `animSpeed`
|
|
- byte `6` bit `0` = `SI_EDITOR`
|
|
|
|
The ScummVM Crusader item update path also preserves a concrete `animateItem()` switch for `animType` values `1..6`, which is enough to reproduce the frame-selection rules even though the exact DOS tick duration is still not directly timed in the live retail pass.
|
|
|
|
## Retail Model
|
|
|
|
### 1. Shared palette-cycle rows drive the flashing colors
|
|
|
|
This part is already directly evidenced from the live NE executable.
|
|
|
|
- `CycleProcess_InitColorTables` seeds the cycle rows
|
|
- `CycleProcess_Update` advances them
|
|
- the rows are written back into live palette entries `8..14`
|
|
|
|
Those same rows already drive:
|
|
|
|
- plain `F7`
|
|
- `Alt+F7`
|
|
- `Ctrl+F7`
|
|
|
|
The editor/helper flashing lane reuses that same machinery rather than inventing a separate color animator.
|
|
|
|
### 2. XFORMPAL makes the low slots matter for translucent editor/helper shapes
|
|
|
|
The editor/helper walls and related helper surfaces are often translucent, and their source pixels disproportionately use the low slot family `8..14`.
|
|
|
|
That means their apparent color is effectively delegated to the current shared cycle rows.
|
|
|
|
In practice, the visible rule is:
|
|
|
|
- if a translucent editor/helper sprite is built from those low slots, its hues will flash when the shared cycle rows change
|
|
|
|
### 3. Some editor/helper shapes also have real frame animation
|
|
|
|
Crusader typeflags also carry per-shape animation metadata.
|
|
|
|
Closed field layout for the Crusader 9-byte row:
|
|
|
|
- `animType` = byte `4` high nibble
|
|
- `animData` = byte `5` low nibble
|
|
- `animSpeed` = byte `5` high nibble
|
|
|
|
Recovered/open-source animation behaviors used by the viewer:
|
|
|
|
- `animType 1` / `3`: increment through frames; `animData` chooses unconditional, 50%, or block-loop behavior
|
|
- `animType 2`: random frame changes
|
|
- `animType 4`: random start, then run through frames
|
|
- `animType 5`: usecode-driven animation hook; viewer leaves this as static because the live script side is not reproduced here
|
|
- `animType 6`: loop from frame `1` while leaving frame `0` as a resting/sentinel state
|
|
|
|
## Viewer Implementation
|
|
|
|
### Metadata fixes
|
|
|
|
The map renderer now carries all three Crusader animation fields through the exported shape definition:
|
|
|
|
- `animType`
|
|
- `animData`
|
|
- `animSpeed`
|
|
|
|
The tooltip trait list now shows all three when present.
|
|
|
|
### Atlas/reference change
|
|
|
|
Static scene exports previously only guaranteed the specific frame used by the authored map item.
|
|
|
|
That is not enough for animated shapes.
|
|
|
|
The reference build now expands visible shapes with nonzero `animType` to include every frame from the shape archive, so the client can step frames at render time instead of getting stuck on the authored start frame.
|
|
|
|
### Palette-cycle reproduction
|
|
|
|
The client now carries a compact rendering descriptor for the low xform-cycle slots:
|
|
|
|
- source slot `8..14`
|
|
- the baked atlas RGBA that corresponds to the current XFORMPAL-remapped translucent output
|
|
|
|
At render time, translucent editor/helper sprites are copied into a small sprite canvas and any pixel matching one of those slot RGBA values is recolored from the current shared cycle-row RGB for the same slot.
|
|
|
|
That lets the viewer animate the same low-slot translucent editor/helper art without inflating the scene payload with raw pixel streams.
|
|
|
|
### Frame animation reproduction
|
|
|
|
The client now steps `animType` shapes using the recovered Crusader rules above.
|
|
|
|
Current approximation boundary:
|
|
|
|
- the semantic frame-advance rules are evidence-backed
|
|
- the exact retail wall-clock tick size is still not directly timed from live DOS execution
|
|
- the viewer therefore uses a stable viewer-side animation step that stays aligned with the already recovered palette-cycle cadence instead of pretending to know the exact original millisecond rate
|
|
|
|
That is good enough to reproduce the visible behavior for map-viewer/editor purposes without overclaiming a closed retail timing constant.
|
|
|
|
## Practical Scope In The Viewer
|
|
|
|
The current viewer pass targets the objects the user actually asked about:
|
|
|
|
- editor-tagged shapes
|
|
- helper/occluding editor geometry
|
|
- translucent editor/helper surfaces that inherit the low cycle slots
|
|
|
|
The frame-animation support is intentionally a little broader than the pure color-cycle support, because `animType` is real shape metadata and some animated map shapes are not strictly editor-only.
|
|
|
|
The palette-cycle recolor stays narrower and only applies to the translucent editor/helper lane where the evidence is strong.
|
|
|
|
## What Is Closed Versus Still Open
|
|
|
|
### Closed enough for the viewer
|
|
|
|
- the shared flashing colors come from `CycleProcess` rows written into palette entries `8..14`
|
|
- translucent editor/helper sprites really do depend heavily on those same low slots
|
|
- Crusader `TYPEFLAG.DAT` carries real `animType/animData/animSpeed` fields in the 9-byte row
|
|
- the viewer can now reproduce both the frame-step and palette-cycle sides in a defensible way
|
|
|
|
### Still open
|
|
|
|
- the exact live DOS wall-clock interval behind the per-item `gametick` animation updates
|
|
- whether any remaining helper families need a different XFORMPAL table than the current viewer default for hue reproduction
|
|
- the full live usecode behavior behind `animType 5` shapes
|
|
|
|
## Ghidra Notes Applied In This Batch
|
|
|
|
This batch also adds concise live-DB comments to keep the provenance visible at the key shared anchors:
|
|
|
|
- `10f8:0336` for the Crusader 9-byte typeflag animation/editor field layout
|
|
- `1438:011b` for the shared palette-cycle row reuse by both F7 overlays and translucent editor/helper colors
|
|
|
|
## Related Notes
|
|
|
|
- [docs/map_renderer/translucency-xformpal.md](translucency-xformpal.md)
|
|
- [docs/editor-object-visibility.md](../editor-object-visibility.md)
|
|
- [docs/f7-overlays.md](../f7-overlays.md) |