Skip to content

Instantly share code, notes, and snippets.

@magcius
Created April 11, 2012 13:25
Show Gist options
  • Save magcius/2359276 to your computer and use it in GitHub Desktop.
Save magcius/2359276 to your computer and use it in GitHub Desktop.
Flash 5 Page Files File Format
FLA format, "Page N" files as found in Flash 5.
Partially reverse engineered by Jasper St. Pierre.
FLA files are CFBF files (COM Structured Storage). You can parse/make them with:
http://msdn.microsoft.com/en-us/library/aa380369%28VS.85%29.aspx
http://git.gnome.org/browse/libgsf
Very helpful while making this:
http://mh-nexus.de/en/hxd/
http://www.mitec.cz/ssv.html
For a trial copy of Flash 5 (Windows):
http://mothball.mecheye.net/Abandonware/Flash5.7z
Unless specified otherwise, format is little-endian.
Formats:
struct LengthString {
uint16_t length;
char name[length];
};
struct Chunk {
char *magic; /* FF FF 01 00 */
/* TODO: could the 01 00 be a count, like the number of contained chunks in
* the structure? Will investigate with multiple layers/frames later */
LengthString string;
char marker; /* 01 00 */
/* TODO: could be related to file magic header, or count in magic */
};
struct PageFile {
char *magic; /* 01 */
Chunk chunk;
}:
For a page file, chunks look like:
CPicPage
CPicLayer
CPicFrame
struct FillStyle {
char *magic; /* 00 */
/* TODO: see comment re: num_fillstyles. Also, this could
* be the type of fillstyle. Needs testing with gradients. */
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
struct LineStyle {
char *magic; /* 00 */
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
char *UNK1; /* 14 00 */
/* TODO: possibly thickness or other attributes? Test. */
};
/* TODO: investigate linestyles -- hairline, thickness, etc. */
struct DrawingVertex {
uint16_t x;
uint16_t y;
char *UNK; /* 00 00 00?? seems to be variable-length?? */
/* TODO: this may be where drawing commands come in here. Test with more vertices,
* and more interesting shapes (curves) */
};
struct CPicFrameContents {
char *UNK1; /* 00 00 00 00 00 80 00 00 80 02 00 00 */
char *UNK2; /* 01 00 00 00 00 00 00 00 00 00 00 00 */
char *UNK3; /* 01 00 00 00 00 00 00 00 00 00 05 */
uint16_t num_vertices;
/* TODO: complete guess, need to investigate */
char *UNK4; /* 00 00 */
uint8_t num_fillstyles;
/* TODO: uint8_t and LineStyle/FillStyle starts with a NUL,
* or uint16_t with a NUL separator? Needs testing with more
* than 255 styles. */
FillStyle fillstyles[num_fillstyles];
uint16_t num_fillstyles;
LineStyle fillstyles[num_linestyles];
char *UNK5; /* 00 00 00 00 */
/* Unknown format for below -- could be operator-based like SWF (LineTo/MoveTo):
* or declarative (each vertex/contour listed -- this maps to JSFL DOM.
*
* XFL maps to both:
* http://stackoverflow.com/questions/4077200/whats-the-meaning-of-the-non-numerical-values-in-the-xfls-edge-definition
*
* Best bet is to see if I can capture an equivalent to a StyleChangeRecord.
*
* When I rearranged some byte sequences in this, Flash didn't care (outside of
* translating the object into a random position -- relative positions and all that), but JSFL listed
* the contours in "reverse" ordering (40 10 10 40) vs. (10 40 40 10).
* Note that changing some of the bytes made the shape disappear - but I haven't tested with
* both line and fill styles -- could be a quirk with rendering out of order or blanking the
* fillstyle.
*
* Let me just paste the bytes and mark what they do. */
char *UNK6;
/* F3 00 00 01 - adding a style makes Flash make the second byte 01, so maybe a StyleChangeRecord? */
/* NOTES:
* * Most (all?) values here are in halftwips: There are 40 halftwips per pixel, and one halftwip is 1/40 of a pixel. */
* * Point values seems to be relative, unsure as to what. First point's values are absolute.
*
* EXAMPLE: Little endian converts this to: 0x0190, which is 400. 400 / 40 = 10.
* The shape is located at (10, 10).*/
DrawingVertex points[n_vertices];
/* Either I'm royally screwing up my math hacking or there seems to be
* something "validating" the byte values -- if they're not arranged correctly
* the shape doesn't appear on the stage. Unknown what the values mean -- for
* rectangles, there are four points. When one of the values that represents
* the "width" increase, the other needs to decrease.
* TODO: test.
*/
char *UNK;
/* TODO: finish. There's names like "Layer 1" at the *end* of the file,
* which reinforces the nested chunks idea: children come first, then
* their own data. */
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment