Field ambient effects
Field maps are not static: water shimmers, waterfalls roll, mist drifts and the ground of one castle pulses under lightning. None of it is animated geometry. It is a small set of runtime mechanisms that repaint the scene’s VRAM or bend its meshes at draw time, authored per scene and started at scene load.
At a glance
| Mechanism | Carrier | Stepper | What it animates |
|---|---|---|---|
| Walker table | scene bundle type-6 slot | FUN_8001ADA4 case 0xB | palette-cell cycling: water, waterfall shimmer |
| Ambient move-VM tree | prescript stager records + MAN partition-1 scripts | move VM + render tail FUN_80021DF4 | palette pulses, texel scrolling, lightning, ambient sound |
| Strips and morphs | move records / bundle type-7 pack | morph stager FUN_8001C604 | texel strip frames, vertex deformation |
| Particle emitter | field-overlay template + MAN section-4 regions | FUN_801D6058 + pool FUN_8003F348 | drifting fog and mist |
The four carriers
Palette walkers
The world map’s ocean animation is not kingdom-only. The asset dispatcher installs any bundle’s type-6 slot, and field init spawns one walker actor per entry. Each walker copies successive frames from a “park” palette row onto a destination cell, so the palette - and every texel drawn through it - cycles.
Twelve bundles ship a populated table: the three overworld maps (eight entries, byte-identical), two single-entry scenes, and a seven-scene family sharing one two-entry waterfall table. Every other scene’s slot is a four-byte placeholder. Resolution is by type byte, not slot position.
The ambient effect tree
Most ambience is a tree of small invisible actors running move-VM bytecode out of the scene’s prescript bundle. A part draws no mesh; its render tail edits VRAM every frame, or it fires sound cues.
Scene entry is not a second mechanism. The placement installer runs each partition-1 placement through the field VM for one frame slice, and every op 0x34 sub-3 that slice reaches installs one stager record - the same instruction a script reaches at run time. The part is seated at the executing actor’s position, not the player’s.
| Render mode | What it does | Seen as |
|---|---|---|
3 - palette-cell HSV cycler | captures a VRAM rect, then every frame converts each texel to HSV, adds the running H / S / V offsets and an optional white blend, and writes the row back (FUN_80019D50) | pulsating flesh, lightning flashes |
4 - VRAM-rect scroller | rotates an authored texel rect in place on a period countdown; no vertex, UV or palette changes | falling water, energy columns |
The pulsating ground never moves a vertex: it is palette-space colour cycling under a static mesh. The bytecode vocabulary these trees are written in is the move VM’s overlay extension. Record 0 of the stager bundle is not an effect at all - it is the scene’s sound-effect descriptor bank.
Strips and vertex morphs
The bundle’s type-7 slot is a vertex-delta pack. A morph lane holds an envelope per actor, and the renderer substitutes the blended vertices at draw time - the source mesh is never rewritten. Move-VM op 0x0A drives the lanes from the ambient tree; a few scenes install theirs from a placed actor instead.
The fog pool
The fourth carrier is a single actor spawned at field init. Each frame it takes twenty-four independent draws, each with a one-in-sixteen chance of bursting one to four particles at a point inside the camera’s visible-tile span.
- The gate is script-driven, not per-scene data.
_DAT_8007B854is raised by op4C 30and cleared by4C 31(see op 0x4C). It is the ambient-particle master gate; it is not an input lock. - The emitter names tiles and draws nothing. Each burst goes to the spawner, which checks the walk box, the region enable and the cap, and fills the pool at
_DAT_8007B7E0- eighty records. - Each record draws as two additive half-sheets, and a sheet is a view-space billboard, not a world-space quad.
- The pool ages once per game frame, by the frame step. The field render pass walks it once a frame and ages each record by its rate times the VSyncs that frame took (
0x1F800393), so a 30 Hz frame ages it by two VSyncs at once. The walk draws no random numbers; only the spawner does. The port steps it once per sim tick on both hosts. - A warp entry - a return from battle, a minigame or a movie - skips the spawn, so the emitter exists only after a real field entry.
Photosensitivity guard
An engine enhancement, not retail behaviour. The casino dance venue’s entry tree runs twenty-one palette cyclers, and one row re-keys its brightness offset between full black and neutral on consecutive ticks - a full-swing strobe far above the three-flashes-a-second guideline. The port’s reduce_flashing option (default on) slews only the applied brightness and white blend toward the simulated target; hue and saturation pass through untouched, and the parts themselves always advance retail-exact. Turning it off restores the retail steps.
In the port
Walker tables decode in scene-formats::clut_walk and animate in engine-scene::clut_walk_anim. The tree is engine-core::world::ambient, installed by the scene-entry pre-run that executes each op 0x34 sub-3 once; its render tails are engine-field::clut_cell_fx and engine-field::vram_scroll. Fog is engine-field::fog_particles and ambient_emitter. The separate volumetric ground fog is an enhancement and never touches this pool.
See also
The install chain instruction by instruction, the part pool and its control block, both render tails, the morph pack format, the fog records and the overworld draw order are in docs/subsystems/field-ambient-fx.md.