Is it text?
In Flash 5 and Flash MX, mostly yes. A script typed into the Actions panel in expert mode is stored as its source text, exactly as typed, with its comments, tabs and line breaks, in single bytes of the author’s Windows code page. A script built in normal mode, by choosing statements from menus, is stored as a list of statements and their fields, from which Flash rebuilds the text. The language is ActionScript 1.0.
In FutureSplash Animator and Flash 1 to 4 it is not text at all. Actions were picked from menus and are stored as commands: a kind of action, then its URL, frame number or target.
In no release is the script compiled in the .fla. Flash turns it into
AVM1 actions only when it publishes the SWF; see
ActionScript in SWF.
| Saved by | Frame revision | Actions are stored as |
|---|---|---|
| FutureSplash Animator, Flash 1, Flash 2 | 4 to 9 | One command per frame |
| Flash 3, Flash 4 | 10 to 18 | A list of commands |
| Flash 5, Flash MX | 19 and later | An ActionScript block: source text, or a normal-mode list |
The ActionScript block
From Flash 5, every keyframe and every movie clip and button instance carries an ActionScript block, even when it has no script. All fields are little-endian.
| Field | Present | Meaning |
|---|---|---|
| u32 | always | The block’s revision: 0 in Flash 5, 1 in Flash MX. |
| u32 | always | The mode. 1: source text follows. 0: a normal-mode statement list follows. 2: nothing follows (seen on Flash MX frames with no script). |
| u32 | from revision 1 | An identifier; its meaning is not established. |
| u32 n, then n × u32 | from revision 1 | Breakpoints: the line numbers where the debugger stops. |
| CString | mode 1 | The script, in single bytes of the author’s code page; see strings. |
| statement list | mode 0 | See Normal mode. |
Later releases add collapsed code ranges from block revision 5; they do not occur in this format. A Flash 5 block (revision 0) is therefore the revision, the mode and the text. The names of the fields and the meaning of the modes come from the JPEXS FLA converter, and were checked against files here. Why Flash MX writes mode 2 for empty frames is not known.
01 00 00 00 01 00 00 00 BE 18 00 00 00 00 00 00 FF 20 1A 0A 2F 2F 2D 2D 2D 2D 20 44 65 66 69 6E 65 … .//---- Define
0x18BE, no breakpoints, then a 6,688-byte script that begins with a line feed and //---- Define a cubeThe text is kept with its own line breaks, usually CR LF or LF. A reader that shows it should decode it in the author’s code page. The explorer uses Windows-1252, the Western European one, so scripts typed on Japanese or Cyrillic systems show the wrong letters.
Frame scripts
A frame script is the block in a frame record (frame revision 19 or later), right after the frame label. Where it belongs is worked out from where the record sits:
- The timeline is the stream.
Contentsgives the scene or symbol name for it, such asScene 1forPage 1. - The layer is the layer record whose children include the frame. Its name follows the last of its frames, so a reader has to read on, or come back to it.
- The frame number is 1 plus the durations of the layer’s earlier keyframes. A keyframe with a duration of 7 at frame 2 covers frames 2 to 8.
The explorer heads each script with exactly this, for example Scene 1 (Page 1),
layer "Actions", frame 9–10 "label" · offset 0x17D in stream "Page 1".
Instance handlers
ActionScript 1.0 lets a script sit on a button or a movie clip placed on the stage, instead of on a frame. It is written as handlers:
on (release) {
gotoAndPlay("menu");
}
onClipEvent (enterFrame) {
_rotation += 5;
}
These are stored in the instance’s own record, on the frame where the instance sits, not in the frame’s block:
- A movie clip (
CPicSprite): the sprite revision, the ActionScript block (from sprite revision 2), then the instance name. - A button (
CPicButton): the button revision, the ActionScript block (from button revision 5; one or more commands before that), a track-as-menu byte, then the instance name.
The explorer labels these scripts with the instance name, or as an unnamed instance, and the timeline, layer and frame where the instance is. See Symbol instances.
Normal mode
In Flash 5 and Flash MX the Actions panel had a normal mode, in which a script was built by choosing statements from menus and filling in their fields. Such a script is stored as a list of statements (block mode 0), not as text. Flash rebuilds the text for display, and so does the explorer.
| Field | Meaning |
|---|---|
| u32 | The list’s revision. |
| u32 | The number of statements. |
| statements | Each: a u32 type, a u32 revision (closing statements carry none when the list revision is 0), and the type’s own fields. |
A statement’s fields are CStrings, u32 words and parameters. A parameter is a CString and a u32 flag: 0 means a literal string, which the text puts in quotes; anything else means an expression, written as it is. From statement revision 2 (revision 3 for types 39, 41, 44, 47, 59 and 80, and 4 for type 37) each statement also keeps the text it was displayed as: three CStrings, a prefix, the text and a suffix, and two u32 (type 24 has a different set). Joined in order, these give the script exactly.
The statement types, as the JPEXS FLA converter lists them:
| Type | Statement |
|---|---|
| 0 | goto: navigation mode, scene, frame, and whether to play |
| 1, 2 | play, stop |
| 3, 4 | toggleHighQuality, stopAllSounds |
| 5, 6, 7 | getURL, fscommand, loadMovie |
| 8 | tellTarget |
| 10 | ifFrameLoaded |
| 11 | on, with the mouse events as bits (below) |
| 13 | onClipEvent, with the clip events as bits (below) |
| 15, 16, 17 | if, else, else if |
| 20 | while |
| 22 | call |
| 23, 24 | setProperty, set |
| 25 | duplicateMovieClip |
| 26 | startDrag |
| 27, 28 | trace, a comment |
| 29, 30, 31 | stopDrag, removeMovieClip, unloadMovie |
| 32 | loadVariables |
| 33 | #include |
| 34 | print |
| 36 | delete |
| 37 | function |
| 39, 40 | var, return |
| 41 | Any other statement, kept as its text |
| 42, 43 | do … while |
| 44 | for |
| 46 | break |
| 47 | for … in |
| 49, 50 | swapDepths, with |
| 52, 53 | continue, switch |
| 55, 56 | case, default |
| 57, 58 | #initclip, #endinitclip |
| 59, 60 | A method call, a method definition |
| 62, 79 | Calls |
| 63, 65, 67 | try, catch, finally |
| 69 | throw |
| 71, 73, 75 | class, interface, import |
| 9, 12, 14, 18, 19, 21, 38, 45, 48, 51, 54, 61, 64, 66, 68, 72, 74 … | Close the block that an earlier statement opened |
The event bits of on (type 11) and onClipEvent (type 13):
| Bit | on | onClipEvent |
|---|---|---|
| 1 | press | load |
| 2 | release | enterFrame |
| 4 | releaseOutside | unload |
| 8 | rollOver | mouseMove |
| 16 | rollOut | mouseDown |
| 32 | dragOver | mouseUp |
| 64 | dragOut | keyDown |
| 128 | keyPress | keyUp |
| 256 | – | data |
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 0C 00 00 00
0D 00 00 00 00 00 00 00 01 00 00 00
29 00 00 00 01 00 00 00 1D 74 6F 74 61 6C 20 3D 20 5F 72 6F 6F 74 2E 67 65 74 42 79 74 65 73 54 6F 74 61 6C 28 29
0E 00 00 00
…
01 00 00 00,00 00 00 00– block revision 1, mode 0: a statement list; then the identifier and no breakpoints00 00 00 00,0C 00 00 00– list revision 0, 12 statements0D 00 00 00– type 13,onClipEvent; revision 0; events01 00 00 00, bit 1:load29 00 00 00– type 41, a statement kept as text; revision 1; the text, 29 bytes:total = _root.getBytesTotal()0E 00 00 00– type 14, the end of the handler, with no revision because the list revision is 0
Rebuilt, this reads onClipEvent (load) { total = _root.getBytesTotal(); },
followed by the other handlers.
Two things are not settled. In the files here, setProperty’s two
parameters are stored value first and target second ("270",
"/text"); JPEXS rebuilds them the other way round, and neither has been
checked against Flash itself. And the explorer does not rebuild every type as text:
method calls (59), class (71), interface (73) and some rarer
types show as a comment holding their strings. None of those occurred in the files
sampled.
Flash 1 to 4 commands
Before Flash 5 there was no ActionScript text. A frame or button action was a command chosen from a menu, such as Go To, Play, Stop, Get URL or Tell Target, with its fields filled in. Frame records up to revision 18, and button records up to revision 4, store these commands. Each command is:
| Field | Meaning |
|---|---|
| u8 | The command’s revision. |
| u8 | The kind of command. |
| CStrings | The URL, the window and the page (scene). |
| u16 | The frame number. |
| … | More fields by revision: labels, targets, variables, whether a field is an expression, key codes. |
Frame revisions 4 to 9 (FutureSplash Animator, Flash 1 and 2) hold one command; 10 to 18 (Flash 3 and 4) a counted list. The layout is the JPEXS converter’s. The explorer does not decode these commands; for a Flash 3 or 4 document its Document section says that the actions are commands, not text.
Included files
A script can pull in another file when the document is published:
#include "Script.as"
.as fileThe #include line is all the .fla holds. The file itself,
plain ActionScript text, stays beside the document and is read only when publishing,
so a document whose .as files are lost cannot be published as it was. The
explorer lists every included file it finds in the scripts. See
the .as file.
Flash MX also added #initclip and #endinitclip, which mark
code in a movie clip symbol’s frame script that runs before the clip is first used;
they are part of the frame script’s text, or statements 57 and 58 in normal mode.
Streams from older releases
Flash rewrites only the streams that changed when it saves. A Flash MX document can
therefore still hold a symbol stream last written by Flash 5, with Flash 5’s revisions
throughout. A reader has to take the revisions from each stream and each record, not
from the document revision in Contents. The stream’s own release shows in
the byte after the class name CPicPage and in the revisions that
follow.
Older copies in free sectors
Because a save leaves the old sectors in place, marked free, earlier versions of
scripts often survive in the free
sectors. In one Flash MX document, an older on (release) handler and a
frame script holding #include "Script.as" are found only there. The
explorer searches free and unreached sectors for script blocks and lists what it finds
separately, as older copies that are not part of the document, with the sectors they
are in.
What the explorer shows
- Every script in the file as one text, each headed by where it is: the timeline, the layer, the frame range and label, or the instance, and the offset in its stream.
- A Scripts table: timeline, layer, frame or instance, label, offset, number of lines and first line. A row opens the sector that holds the script.
- The included files.
- The older scripts found in free sectors, separately.