Reviewing Flash Decompiler Trillix

Eltima recently released a new decompiler aptly named Flash Decompiler Trillix. According to flash-decompiler.com “Flash Decompiler Trillix is the only application capable of converting SWF to FLA with high speed, high quality and hundreds of additional features.” A pretty loaded statement, so I thought I would take a look at it and see if they live up to their marketing departments self praise.

I am reviewing the mac version of this software, I haven’t looked at the PC version as I swore off PCs years ago. I assume both versions and their GUI are identical.Flash Decompiler Trillix default interface

Upon launching the app you are presented with a non-traditional application. It has no OS chrome, sort of looks like something created in AIR, but dated – sort of like a classic mProjector app (for those who remember mProjector). The applications footprint is small but it is packed with options. Almost overwhelming at first. The app does have some nice features, but the GUI design just doesn’t do them justice.

For this review I decompiled three swfs, a compiled ActionScript 3 project with no timeline, a timeline based project that has some Actionscript code spread out on the timeline, and a Flex project (essentially a complex ActionScript 3 project with no timeline so I won’t write my review of this, I do make a few comments and suggestions about decompiling the Flex framework below).

ActionScript 3 project with no timeline

The ActionScript 3 project I chose to decompile is very complex. 110 classes, thousands of lines of code, and not a single timeline in site (just how I like it).

The first step is to select the source swf as the instructional text states, easy enough, I select the “…” button next to the SWF file name field. Not sure if “…” is the best labeling, I know what it means, not sure if everyone will. Next I select the path of where I want the decompiled FLA to be saved. Again, I select the “…” button next to the FLA file name field. By default it chooses the same directory as the SWF and appends _conv to the file name. The problem I have with the GUI is it doesn’t show you the full SWF or FLA path. If you don’t click on the “…” browse button you have no idea where the FLA will be saved.

Next I have to select my decompilation settings from a massive list of about 70 options. I wasn’t kidding when I stated the interface was a little overwhelming. Luckily they have a settings filter so you can drill down to the exact settings you are looking for. It still doesn’t hide the fact that there are 70 or so options. All of these options have a default selection which I assume are the most common selections.

Some of the options are fairly straight forward such as File Format and SWF Version. However, some of the options are very confusing. The one that confused me the most was the ActionScript 2.0 toggle? The website told me that this app can decompile ActionScript 3.0 swfs, but the toggle label says Actionscript 2.0 and is checked by default? If I uncheck this does it mean it will decompile to Actionscript 3.0 or will it think it is ActionScript 1? The contextual help for this toggle doesn’t mention anything about ActionScript 3. “Toggle ActionScript 2.0 decompilation on/off. If not enabled ActionScript 1.0 will be generated”. This option should use a combo box and the combo box should populate itself based on the SWF Version option selected above. Obviously if the user selects Flash Player 6 SWF Version the ActionScript toggle shouldn’t offer the opportunity to select ActionScript 3. After playing around with this toggle I came to the conclusion that it doesn’t really do anything, AS3 is retained no mater what.

Another confusing option is in the SWF version combo box. One of the options is “same as FLA”, I know what they are attempting to do here but not everyone is going to know that Flash MX 2004 is Flash Player 7.

Personally the Page options section I feel is not needed. It’s been a while since I have actually used the Flash IDE but I am pretty sure it remembers settings from the last time it was used. Do I really need to select if I want rulers visible when the file opens? There are way too many options in here for the average user, just trying to scale this massive list of 70 options down. Or maybe move these options to an optional options section that doesn’t show by default. KISS – Keep it Simple Stupid.

Lastly, the contextual help on a lot of the options are completely useless. For example, one option label is “Decode all classes as dynamic”. The contextual help for this option is “Decode all classes as dynamic”. I know what this means, does the average user?

I think a few very important options have been left out. One would be an option to not decompile Flex Framework classes, as you will see below in my Flex project decompilation there are a lot of excess classes decompiled for no reason. I guess there is a reason if you don’t have the Flex framework already on your machine. How about an option to create a swc of the Flex framework so the user doesn’ t have to wade through excess classes?

Another nice option would be export ActionScript only. Some of us don’t care about FLAs. Edit, I just figured out that you can extract only the AS, you have to select the Extract button and uncheck everything but scripts.

OK, enough of that, lets take a look at the decompilation results, after all that is what is important here.

First off, the decompilation was fast, less then a second which is very impressive. Once the compilation is complete it automatically opens the decopiled FLA in the Flash IDE (this is one of the 70 options you select). The decompiler created a project file and the project panel is opened automatically. I do not have a copy of Flash CS4 yet, I wonder if the gProject panel would still work. I would assume the gProject panel is backward compatable, if not there would be a lot of complaints by now I’m sure.

All 110 classes in my ActionScript project were decompiled and all of the class paths (directories) are correct. All the code is representative of what it was pre-compile with a few notable differences.

1. All local variables do not retain their names. For example, if I had

var foo:String = “bar”;

in my code, after it is decompiled the var looks like

var loc1:*;
loc1 = “bar”;

I understand the renaming, the compiler changes the name of  local vars to something representative to their position in memory allocation and Trillix is masking those unreadable names to something that is somewhat readable. What I do not agree with is the formatting, variable defined on the first line, value assigned to it on the second line. Pre-compilation it was all in one line.

Also vars which aretyped as String pre compilation are typed as a wildcard (*) when decompiled unless you implicitly cast the value to whatever you typed it as. For example:

var foo:String = String(bar);

will decompile to this:

var foo:String;
foo = String(bar);

Does anyone know if the compiler does this after it validates the type upon compilation, or is the decompiler being a little lazy? Interestingly if you type your var using as:

var foo:String = bar as String;

it will decompile to:

var foo:*;
foo = bar as String;

not cool.

Lastly, all of the local vars are moved to the top of the method. If your code look like this before compilation.

private function foo(bar:String):String {
     if (bar != ‘local’) {
          var thing:String = String(LoaderInfo(OS.instance.root.loaderInfo).parameters.thing);
          return thing;
     }
     return bar;
}

It will look like this after decompilation

private function foo(arg1:String):String {
     var thing:String;
     thing = null;
     if (arg1 != ‘local’) {
          thing = String(LoaderInfo(OS.instance.root.loaderInfo).parameters.thing);
          return thing;
     }
     return arg1;
}

2. Along the same lines as above, all method arguments names are changed to arg1, arg2, etc. The good thing is method arguments keep their proper typing and are not wildcarded like the local variables.

3. Oddly enough all class level variables are moved to the bottom of the class, again a personal opinion, I prefer them at the top. Good news is, class level variables retain their original name and typing.

4. All import statements are wildcarded, again, not sure if this is something the compiler does. In AS2 this would have been a larger issue as all classes in the wildcarded package would be compiled into the swf. In AS3 classes are only compiled into the swf if they are instantiated. So even if you import flash.display.* doesn’t mean that Loader is available at runtime anywhere in your compiled movie, you actively have to instantiate Loader by calling new Loader() somewhere in your code. From a personal standpoint I have seeing wildcarded imports, just seems lazy and sloppy. I’m sure others will disagree.

5. And of course, comments are not decompiled. This is because comments are stripped out during the compilation process.

6. Lastly, all for loops are converted to while loops (for each loops remain for each loops). This is the same as AS2, the compiler converts all for loops to while loops at compile time, not sure why, but I am sure there is good reason.

All and all I am very impressed with the decompilation of my Actionscript project. I was able to recompile my project again based on what was decompiled. The only issue I ran into was when a swc was compiled against, obviously the decompiled version would have no reference to the swc used at compile time. Most of my code issues mentioned above are minor and of a personal nature. The UI issues I mentioned are more severe and I hope are updated in a future release.

 Timeline Based Project with Actionscript 3 On Multiple Keyframes

Since I don’t spend a lot of time on the timeline this part of the review will be quick. Again, the decompilation of the swf was very quick. Less than a second. Once the decompilation was complete the Flash IDE opened and there was my FLA. The timeline, including my tween were completely restored, however my layer names were dropped (expected, the layer names are not compiled into the swf).

The big problem is all my timeline actionscript code was gone. Or was it?

The decompiler, actually the compiler does this behind the scenes, a class file is created for every display object and the class is linked to the display object in the library. This could be very confusing for a flash animator who doesn’t use a lot of code, and has never used external class files. I couldn’t find an option that dropped the actionscript back onto the timeline. That would be ideal.

Conclusion

I am very impressed with the output of the decompiled code. It is clean and readable. I have a few issues with how variables are declared (see above). With all the options in the GUI I wish there were more code preference options. I really have an issue with the GUI. It looks like they tried to jam too many features into a widget type design. Personally I think the design is a little dated and should have more of an applicationesque look to it.

All in all I am impressed. I will most likely use this application on a reglular basis.

4 Comments

  1. …I guess that’s a fat “NO” to your “I assume both versions and their GUI are identical” 😉

  2. Anonymous Coward

    > I haven’t looked at the PC version as I swore off PCs years ago

    Last time I checked, “PC” meant “Personal Computer”. Despite what the Apple marketing dept. would have you believe, a Mac is also a PC.

    /troll

  3. Ashera

    Regarding what the decompiler does to local variables — that’s what flash does when it compiles your code. There’s only function-level scope, so all variable declarations are put at the top of the function. If you had a declaration + assignment (e.g. var foo = “bar”), that gets split up into two statements by the compiler. The declaration is put up top, and the assignment stays in its original location.

    Try running these functions

    function test1() {
    trace(“foo: ” + foo);
    var foo = “bar”;
    trace(“foo: ” + foo);
    }

    function test2() {
    trace(“not defined: ” + notDefined);
    }

    test1() will trace out:
    foo: undefined
    foo: bar

    The first time, foo exists but hasn’t been given a value yet. In the second one, it has a value.

    test2() will result in an “Error 1120: Access of undefined property” error.

Leave a Comment

Your email address will not be published. Required fields are marked *