Crusader_Decomp/docs/map_renderer/editor-item-animation.md
2026-04-02 01:15:16 +02:00

8.6 KiB

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
  • 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.

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