Score, Stage, and Playback
The Score timeline, channels, sprite spans, markers, navigation commands, tempo, transitions, and the Stage.
The Score
The Score is a grid: frames across time, channels down the page. Playback is the movement of the playback head across frames.
frame: 1 2 3 4 5 ...
tempo channel [ 30fps ][ 15fps
palette chan [ system palette
transition ch [ ][dissolve]
sound 1 [ theme.aif ]
sound 2 [ ][click ]
script chan [ L1 ][ L2 ] <- frame behaviors
channel 1 [ background bitmap ] <- sprite spans
channel 2 [ logo ][ menu panel ]
channel 3 [ button A ]
...up to 1000 sprite channels (MX 2004; 120 in D6, 150 default)- A sprite span is one sprite occupying a channel across consecutive frames, with keyframes for tweened properties.
- The script channel holds one frame behavior per frame (the "frame script").
- Effects channels: tempo, palette, transition, two score sound channels.
- Channel count:
the lastChannel; movie propertythe scoreexposes raw score editing underbeginRecording/endRecording(score recording, authoring-oriented but runnable in projectors).
Drawing order
Higher-numbered channels draw in front of lower-numbered ones. Runtime locZ overrides visual order without moving channels: sort by locZ (default = channel number), ties broken by channel. This dual system (authored channel order + runtime locZ) must survive in any reimplementation.
Markers and navigation
Markers (labels) name frames:
go to frame "menu" -- jump to marker
go "menu" -- same
go to frame 15 -- numeric
go the frame -- loop on current frame (THE idle idiom)
go loop -- to previous marker (or current marker frame)
go next / go previous -- marker-relative
marker(0) -- frame of current/previous marker
marker(1) / marker(-1) -- next/previous marker frame
the frameLabel -- label at current frame (VOID if none)
the labelList -- RETURN-delimited string of all labels
label("menu") -- frame number of a labelplay / play done is navigation with a return stack:
play frame "help" -- push current location, go
play movie "credits" -- cross-movie call
play done -- return to pushed locationMovies that play without play done leak return-stack entries; the stack survives until the movie ends.
Cross-movie navigation: go to movie "other.dir" replaces the current movie (globals, actorList, timeouts, and open MIAWs persist; the new movie gets the full start event sequence). gotoNetMovie is the streaming variant.
Tempo and frame advance
- The tempo channel sets frames-per-second;
puppetTempo fpsoverrides from Lingo. - Tempo also supports wait states (wait N seconds, wait for mouse click/key, wait for cue point) in the authored channel.
- The playback head advances when the frame's work completes AND the tempo interval elapsed; heavy handlers slow playback below tempo (no frame skipping: Director never drops logic frames).
the frameTemporeads the current authored tempo. Actual achieved rate depends on machine speed.updateStage()redraws mid-handler without advancing the head (and triggersstepFrame);go the framere-runs the frame cycle.
There is no vsync contract: classic Director timing is best-effort wall-clock pacing. Deterministic emulators usually pace with the documented event order from Event lifecycle and a wall-clock tempo governor.
Transitions
The transition channel (or puppetTransition n) applies a wipe/dissolve when entering the frame, between the old and new frame images. Transitions block the frame cycle while animating (events largely pause). Rarely critical for game preservation but visually distinctive; the classic transition IDs 1-52 are stable across versions.
Palettes
The palette channel selects the active 8-bit palette per frame span; puppetPalette overrides. On 8-bit displays this remapped the whole screen; on modern 32-bit rendering, the active palette matters for decoding paletteIndex colors and 8-bit member pixels. Palette transitions (fade to black/white, color cycling) animate palette entries over time.
The Stage
(the stage).rect -- screen placement of the playback window
(the stage).drawRect -- where the movie draws inside the window (scaling!)
(the stage).sourceRect -- authored stage size at origin
(the stage).image -- read back the composited frame (D8+)
the stageColor -- background color index/rgb
the fixStageSize -- block movies from resizing the stage
the centerStage -- center on movie changedrawRect vs sourceRect is the official scaling mechanism: setting a larger drawRect stretches the whole rendered movie. Projector flags (CenterStage, ResizeStage, FullScreen) interact with these; the recovered native recompute logic is documented in Native stage and presentation.
Score recording (dynamic score)
beginRecording
repeat with f = 1 to 20
go to frame f
sprite(2).locH = 40 + f * 5
updateFrame
end repeat
endRecordingScore recording writes authored score data from Lingo: insertFrame, deleteFrame, duplicateFrame, updateFrame, clearFrame, frameScript, frameTempo, framePalette, frameSound1/2, frameTransition, and sprite property assignment all become score edits between beginRecording/endRecording. Some shipped titles generate their scores this way at startup; an emulator needs at least append-style recording to run them.
Film loops
A film loop member packages a score excerpt as a single reusable animated member: placing it in one sprite plays its internal channels inside that sprite's box, honoring the outer sprite's ink/blend. Internally it is a nested score render, not a pre-baked animation; sprite properties inside the loop keep meaning (see rendering notes).