Flash for Windows was written with Microsoft’s MFC library, and it saves its documents
the MFC way: each object writes its own fields into a CArchive, and MFC adds
tags that say which class each object belongs to. Every stream of an FLA except the Media
streams is such an archive. The class tags and strings below are MFC’s own scheme; the
records inside are Flash’s. All numbers are little-endian.
The start of a stream
A Contents, Page or Symbol stream starts with
one byte. In a timeline stream it is 01, and the root object, a
CPicPage, follows with its class tag. In Contents the first
byte is the document revision, and the document’s fields follow directly; see
The Contents stream.
Strings
Text is written in MFC’s CString archive form, and in this format in its
Unicode form: the three bytes FF FE FF, then the length in characters,
then the characters in UTF-16LE.
| Length in characters | Written as, after FF FE FF |
|---|---|
| 0 to 254 | One byte, the length |
| 255 to 65,533 | FF, then the length as a u16 |
| more | FF FF FF, then the length as a u32 |
FF FE FF 06 73 00 74 00 6F 00 70 00 28 00 29 00 ....s.t.o.p.(.).
FF FE FF 00
FF FE FF F9 2F 00 2F 00 …
stop(), an empty frame label, and a 249-character script that starts //No terminating zero is written. The marker works because FF FE as a u16
after FF is a length MFC never writes in the single-byte form, so a reader
can test every string: FF FE FF means UTF-16, anything else a single-byte
string with a length of 0 to 254 bytes, or FF and a longer length. Single-
byte strings still occur in this format, in streams last written by Flash MX or earlier
(see documents that mix
encodings); a reader should test each one.
Stream names inside Contents are written differently from CStrings: one
length byte, the number of characters, then UTF-16LE with no marker. See
Stream names and display
names.
Revisions
Flash’s records version themselves. Every record starts with its own revision byte,
and each release that changed a record raised its revision and added fields at the end.
A reader reads the revision first and then only the fields that revision has, so one
reader can read every release of this format. The object part that every timeline
object starts with is revision 2 in Flash MX 2004, 4 in Flash 8 and 5 in CS3 and CS4; a
frame record went from 0x17 in Flash MX 2004 to 0x1D in CS4.
The values of each release are on the Versions
page, and each record’s fields by revision on
Pages, layers and frames.
Flash rewrites only the streams that changed, so a timeline stream can be older than
the document around it. A reader should take each stream’s revisions from the stream
itself, starting with the byte after the class name CPicPage, not from the
document revision.
Classes
These classes are declared in the streams of files examined for this site:
| Class | Where | What it is |
|---|---|---|
CPicPage | Page and Symbol streams | A timeline: a scene or a symbol. The root of the stream. |
CPicLayer | Page and Symbol streams | A layer. |
CPicFrame | Page and Symbol streams | A keyframe, with its duration, label, sound and script. |
CPicShape | Page and Symbol streams | A shape drawn on the stage. |
CPicSymbol | Page and Symbol streams | An instance of a symbol; movie clip and button instances add their own fields to it. |
CPicSprite | Page and Symbol streams | A movie clip instance, with its handlers and instance name. |
CPicButton | Page and Symbol streams | A button instance, with its handlers and instance name. |
CPicText | Page and Symbol streams | A text field. |
CPicBitmap | Page and Symbol streams | A bitmap placed on the stage. |
CDocumentPage | Contents | A scene record: its stream name and display name. |
CColorDef | Contents | A colour definition. |
CMediaBits | Contents | A bitmap’s media record: its stream name, display name and source file. |
Kreijstal’s notes on fla-decoder list the rest of the set, among them
CPicMorphShape, CPicVideoStream, CPicSwf,
CPicOle, CMediaSound and CQTAudioSettings.
The class names are Flash’s own, as they appear in the files; Macromedia and Adobe
never documented them.
Worked example
The first 64 bytes of the Page 1 stream of a Flash 8 document:
00000000 01 FF FF 01 00 08 00 43 50 69 63 50 61 67 65 04 .......CPicPage.
00000010 00 FF FF 01 00 09 00 43 50 69 63 4C 61 79 65 72 .......CPicLayer
00000020 04 00 FF FF 01 00 09 00 43 50 69 63 46 72 61 6D ........CPicFram
00000030 65 04 00 FF FF 01 00 0A 00 43 50 69 63 53 70 72 e........CPicSpr
01– the stream’s first byte: the root object followsFF FF 01 00 08 00 "CPicPage"– a new class, schema 1, an 8-byte name (index 1; the page takes index 2)04 00– the page’s object part: revision 4, which says Flash 8, and flags 0; its children followFF FF 01 00 09 00 "CPicLayer"– the first child, a layer of a new class (indexes 3 and 4), then04 00FF FF 01 00 09 00 "CPicFrame"– the layer’s first frame (indexes 5 and 6), then04 00FF FF 01 00 0A 00 "CPicSprite"– the first thing on the stage in that frame, a movie clip instance
The same stream in a Flash MX document has 01 where this one has
04. Only after the instance, the frame’s other children and the end tag
00 00 come the frame’s own fields, and after all the frames, the layer’s
name. See Pages, layers and
frames.