Research on .FLA file format


FLA Notes


Files used (and contents thereof): lightningbeam.org/Flash_tests.zip


The sequence 0xFF 0xFE 0xFF reccurs a lot.
- According to Benjamin, this is the separator - that would explain it.


Convention: All strings given in quotes have each character separated by 0x00
(i.e, "string" = s 00 t 00 r 00 i 00 n 00 g 00)
Strings given literally (like CPicFrame) have no separator.




Symbol X:
All CPic* sections are preceded by 0xFF 0xFF 0x01 0x00 0x09 0x00 except 
the first one (CPicPage).
Added curve to rectangle; this removed the CPicShape section.
- Initial analysis of CPicShape:
53 bytes long (counting '0xFF 0xFF 0x01 0x00 0x09 0x00 CPicShape')
Ends in 0xFF 0xFF - I think this is a separator sequence. (Yes - see note 1.)
Changed color of shape to 0DEADF. Searched in binary file.
- Initial analysis of CPicFrame:
Color identifier (0x0D 0xEA 0xDF 0xFF) after 32 bytes past 'CPicFrame'. 
Nice number.
I am going to stop explicitly putting 0x before each byte, I think it's clear enough.
Moved one vertex along X axis. Changed 4 bytes: 70 0F -> A0 14, and farther 
along 00 00 -> D8 FA.
Taken in context: 30 70 0F 00 | 00 30 00 00 -> 30 A0 14 00 | 00 30 D8 FA
By vgrep they are the only changed bytes, so they must encode the position of 
the vertex. I don't know what the precision is, let me see.
After a small-as-possible movement, they are 30 28 14 00 | 00 30 50 FB. I am 
guessing the first is a float for the width; but I don't know what format it's in 
(IEEE 754 gives crazy values that are in the range of 0.00001 - 
0.0000000000000000000000000000001 depending on which bytes I use).
I moved the vertex again mostly along the Y axis this time. All of a sudden there is a whole lot
of change; the file itself is 4 bytes shorter. The change starts 8 bytes after the color, 1
byte before a word boundary. Hold on.
Well, I still haven't sorted out the number format, but everything starts 1 byte before a 
word boundary. And the only change in the files is between the 8-byte point and
the previously changing bytes.

Contents:
Contents starts with 16 bytes, followed by CDocumentPage, followed by two bytes 
(17 06), followed by "Page 1", followed by 4 bytes (FF FE FF 07), followed by 
"Scene 1". Following that are 22 bytes, and then "GO". 


Page X:
Quite a lot changes when a symbol is added. Including the following XML:
<component metaDataFetched='true' schemaUrl='' schemaOperation='' sceneRootLabel='Scene 1' oldCopiedComponentPath='1'>
</component>
Also, the CPicData section is followed immediately by FF FF 01 00 "\n" CPicSprite.
 I believe the XML is in the CPicSprite section.



Reference Notes:

  1. Established that FF FE FF is the separator.

24 comments:

  1. I am making some really good progress with lines, I have figured out how to create a line, but have not been able to test it because I cannot create, nor modify, archives of the correct type with 7zip. Any ideas on how to package the files back into the original? Was just about to see about modifying the fla directly, don't remember if the files were stored compressed or not.

    Also, the vector data (positions, dimensions, etc) in my fla files are pixels*40, as an integer, so basically in 1/40th pixels. Its some variation on the "twips" concept, though I've seen varying interpretations of what a "twip" is.

    I will post more detailed information when I can, I have 3 010 editor template files which describe (partially) the Contents file and the "P" files. 010 editor templates are basically a bunch of C structures that describe a file, with some dynamic stuff thrown in. I'll paste them up shortly so you can see what I mean.

    ReplyDelete
  2. Um, I had posted a comment, but it appears to have disappeared... I have a copy of it I can repost, but wasn't sure if it was because you are moderating posts. I was able to successfully modify an FLA file to add a new line. Will be attempting to add a rectangle next to see what that looks like.

    ReplyDelete
    Replies
    1. I am not moderating posts, but Blogger decided it was spam for some reason. I marked it as 'not spam' and hopefully that won't happen again.

      Delete
    2. Ok, heading to bed, but wanted to update you first. I have got quite a bit figured out. When I had just lines, I could find the "instructions" for drawing those lines which came down to 2 instructions: "move absolute, draw relative" (MADR) and "move relative, draw relative" (MRDR). The instruction type (opcode) is 2 bytes, and each of them is followed by 2 pairs of shorts, either an absolute position, or a relative offset. As I added line segments, the new segment appeared at the beginning of the list, used an MADR instruction, and converted the previous first from an MADR to an MRDR. When I added the Rectangle, I couldn't figure out what was going on, so I backed up and started with just a rectangle. 2 new opcodes appeared. I figured out they are something like: "start fill, move absolute, draw relative" (SFMADR) and "draw relative" (DR). I went back to the original file with a rectangle and 4 lines, and found everything, however, after the SFMADR and 3 DRs needed for the rectangle, there were three bytes in the middle that I didn't know what they were there for... I'm going to stop this thought because I may have figured it out, but not sure, and don't have time to look right now, so I'm going to leave it at this.

      Delete
    3. Wow, that's really helpful! When we have the draw instructions figured out, then I can start to implement 'import FLA' in Lightningbeam (albeit only importing simple shapes).

      Delete
    4. Yeah, I hope to look at this some more tonight, but I also forgot that I suspect I'm actually looking at the wrong version. I think there are two older versions using the compound format. I noticed you had nicely named files, while I ended up with a "Contents" file and a "P 1 1328458108" file. Is this just because I haven't named anything, or because of differing file formats? Hopefully, the drawing instructions haven't changed much if this is the case.

      Delete
    5. That I don't know; it may be that they are different versions or it may be that it is because I am using a different library to extract them. What version of Flash are your files created with?

      Delete
  3. They are made with the latest version (demo), but are saved as flash 4 ".fla"s

    ReplyDelete
    Replies
    1. That may have something to do with it then. Mine are made in Flash 8.
      I wonder whether the opcodes are similar to those in SWF files?

      Delete
    2. I checked into SWF (thought I mentioned I was going to do that, but looks like my post got filtered again) and it does not look like it matches very well, however there are probably similarities, so I will look at it closer. Looking at http://www.m2osw.com/swf_alexref, it looks like SWF has been designed to be extremely compact, packing things at the bit level, trying not to waste any room, which FLA does not seem to be doing, at least not much. Might have found one place where they do it minimally, but definitely not to the extent it is done in SWF. I made very little progress last night, just didn't have much time, and I've been sick, so I tried to get some extra sleep. I'll let you know if I make any big discoveries, and maybe will post some details with an example, though that might not happen for another day or so.

      Delete
    3. Well, I ended up wasting my time tonight attempting to code a primitive loader into the app. I failed miserably, lol. I was finally able to make a menu item, get a file, open it, parse it, created an svlgui.Shape... but then I didn't know what to do next... so, if you can tell me how to view that shape I made, that would be wonderful. Still struggling with the instruction format, there are some bits/bytes that I'm not sure of and get in the way. We'll get there!

      Delete
    4. All shapes must be added to be drawn. The simplest thing is to call root.add(yourshape) and then MainWindow.stage.draw() to update the view.

      Delete
    5. Well, there are 2 interrelated problems. Background: My code ended up in GUI/Generic/GApplications.py because I couldn't figure out how to add an "Open .fla" menu option anywhere else, nor how the regular "Open file" worked. I can't access root nor MainWindow from here directly, which is where the two problems come in.

      1) I attempted an "import lightningbeam" within my function, and strangely every time I would select a file, a second main window would pop up. Finally determined that this was caused by your lack of a "main" method in lightningbeam.py, and all of the code outside of function declarations was getting called. I wrapped what looked to be the important code in a function, and added a block to call it appropriately.

      2) Once I did this, I still couldn't access the root and MainWindow variables.

      So, I'm sure that there is some simple thing I'm missing (maybe not, lol) but if you can pass along a suggestion, I would be happy to hear it.

      Delete
    6. Ok. The problem here is that I didn't really plan for add-one, which I should rectify. But in the meantime, the 'Open file' function is in lightningbeam.py, in the open_file method. You should be able to duplicate this. As for the menu: there is a call to svlgui.menufuncs, with the building blocks of the menu. Assuming your method is called import_fla, you could add to the "Import" array the following tuple:
      ("Import .FLA",import_fla,"/F")

      Delete
  4. Ok, I have basic drawing down, in a basic fla. I can handle an fla that only has stuff drawn on the stage right now, but I can handle lines, closed shapes, and curves. However, there are a few problems.

    1) I don't know how to control the line width. I know what it is supposed to be, but don't know how to set it.

    2) I know this is due to the same limitation in swfc, however, separate lines of a shape cannot have different properties, while they technically can in flash (filled rectangle with 4 different colored sides). This can be mimicked by creating multiple shapes though.

    Looking at gradients next, briefly looked at your base3 sample, which I suspect involved converting a drawn shape to a MovieClip symbol, but I didn't look too closely. I'll post links to pictures of Flash and Lightningbeam showing the same fla in just a few minutes.

    ReplyDelete
    Replies
    1. Here is LB next to Flash, both showing the same fla. http://digitalseraphim.freehostia.com/lb_fla_example.png

      As you can see, the edges in Flash are thicker, as they are set to 2, but I didn't see how to control that in LB. I know what value to use, but just not how to. We are getting there!

      Delete
    2. Wow! Can I put that image on the Screenshots page?
      1) I pushed a new revision to Github which has support for line widths (set the linewidth property of the shape).
      2) This is true, although in Flash a shape is often a group of shapes anyway - and I am probably going to make the fill separate from the line so you can have not-entirely-outlined shapes.

      Delete
    3. Definitely. I'm pulling the new code down now. (I keep forgetting that some of these messages are replies, and if i just type into the box at the bottom it will end up another top level message. Need to slow down, lol)

      I got the code and am setting the line widths. Do you know how to set up antialiasing with the drawing? I looked into GDI+, and thought I had found the way, but it didn't do anything when I tried. Low priority, but would look a little better.

      Also, I know you don't use windows much (if at all) and the windows GUI has some "quirks" that could use some improvement. I haven't looked into it, but if you could tell me where the code to layout the window is, I would be more than happy to touch it up. UI design is another interest of mine :^)

      Delete
    4. I really don't know how to antialias on Windows (it happens automagically on Linux and Mac), but you could always try drawing four or so times, offset by a quarter pixel. The layout code is in lightningbeam_windows.py, in MainWindowOSX (the naming is because I was initially only going to use PyGUI for OSX - I really should change that!)

      Delete
    5. I figured out that it is using GDI+ for doing the drawing in windows, and found GdipSetSmoothingMode which is supposed to do smoothing. As the second parameter it takes an enum value for how to do the smoothing, but I couldn't figure out where to put it. I tried putting it in the "from_hdc" "from_dc" and "from_image" methods within the GUI/Win32/GDIPlus.py -> Graphics class, which I found all get called very often, and this did not change anything.

      On a related note (to this part of the conversation, but not to the page), have you thought about switching your ui code to something more cross platform? I found http://kivy.org which supports Android, Linux, Windows, and OSX. This would greatly simplify the UI code, as well as providing multitouch support in the future (very handy for doing drawings on a tablet). What are your thoughts on this? Would be interested in helping out if you want. (My interest in my previous "distraction" of doing UDK/Scaleform stuff has waned, due to the fact that it is almost impossible to do for free, and making LB a useful and solid alternative to Flash would serve that goal greatly)

      Delete
    6. I actually had never heard of Kivy. I was originally using GTK, which was great on Linux and worked ok on Windows but was a complete pain to get running on OS X. I moved to PyGUI for precisely that reason (to have something be more cross-platform compatible); however, PyGUI does have some limitations (such as a lack of image buttons and no ability to transform a canvas context). Yesterday I started looking into two alternatives: Pyglet and Pyjamas. As Kivy provides the same benefits as Pyglet (OpenGL acceleration, etc.) as well as some things it lacks (e.g. UI elements), I will replace Pyglet with Kivy in my inquiries. I am still going to continue research on Pyjamas, as it will allow for creation of a web app (but not hardware accelerated). If you would like to help out on this, that would be great!

      Delete
    7. I note that Kivy has to be compiled to be installed, unlike PyGUI, which means I would have to provide architecture-dependent packages. Still, that isn't too big of a hassle.

      Delete
    8. Ok. Over the next few days I will mock up a Kivy front end (with no actual functionality at first) and post a pic. Then I will start to add functionality to it, and we can see how it goes from there. It does look like Kivy might be a little cumbersome on the installation aspect (wrt dependencies and such) but we will have to see if its other aspects outweigh this issue. I'll keep in touch.

      Delete
    9. So.... Kivy is awesome.... However, it's not right for the job. It is awesome for interactive graphics, not so good for what we want to do. In looking over the other frameworks available, and not really seeing anything I like... but I'm picky... So, just ignore me, other than my comment about Kivy... not for this.

      Delete