Flash GPU experiments

August 3rd, 2009

With the release of Flash 10, Adobe added some support for GPU’s via OpenGL and DirectX. The Flex SDK currently offers no way to flag any appropriate bits for this, so recently I endeavored to set this bit myself and see what the wonders of the GPU had to offer.

I wrote a small script to do this, but there is no way I have found to actually know if it’s working, save for graphical anomalies in some circumstances. I couldn’t see any difference in Linux (even with Compiz turned off), so I loaded up ye olde XP and tried it there with no obvious results.

Frustrated, I tried manually setting the wmode of the swf in an HTML page and finally saw some differences (although only in XP). Unfortunately the framerate decreased, something that I suspected might happen, but even worse the framerate seemed even more inconsistent and choppy than under regular rendering modes. It might’ve been because I was using it inside a browser or maybe due to my numerous framerate shenanigans. But more importantly the bit I flipped seemed to do nothing at all.

So while at first I was miffed at being left out of the Flash GPU club, now I’m content to wait longer. There’s no indication of what, exactly, these features are supposed to offer that I’ve found, nor any way to even be sure if you’re getting any benefit/hindrance from them. Unless you’re in Windows and have an eye for graphical anomalies I suppose.

Here’s the python script I used to set the aformentioned UseGPU bit (from the command line: python setusegpu.py <swf>). You can modify it easily to set the UseDirectBlit bit too (see the code for details). I’d love to hear if anybody can get better results than me, or maybe tell me how wrong and foolish I am and I’ve been misinterpreting everything.

After adding a custom event to something I was coding up today I started intermittently receiving something like this error message:

TypeError: Error #1034: Type Coercion failed: cannot convert flash.events::Event@148cb29 to com.brokenfunction.CustomEvent

It came with no stack trace, no line numbers, and had no determinable source. In other words, it was incredibly annoying. I had recieved this message before because I had not implemented clone(), but clone() was working properly now, what could be the cause? I pressed the play/pause button on my keyboard while pondering this and it triggered the error message. More research indicated it had nothing to do with any keyboard events, and was actually due to the player apparently quickly losing and then gaining focus. Why my OS sees fit to do this is still an unsolved mystery.

For my CustomEvent I had a couple types, including ACTIVATE and DEACTIVATE, which are already handled by Event but I added them anyway (var ACTIVATE:String = Event.ACTIVATE) so I wouldn’t even have to import Event when using my CustomEvent. So, on a hunch I changed the values of ACTIVATE to a different string and it fixed the bug!

The EventDispatcher I used to dispatch my CustomEvents was completely isolated so I foolishly thought it wouldn’t actually start broadcasting events implicitly – I was wrong. EventDispatcher still dispatches ACTIVATE/DEACTIVATE (when the player focuses/blurs) no matter what. I presume the error message came up when listeners were expecting a CustomEvent and got an Event instead. The lack of a stack trace could be explained by the fact that there is no stack to trace, as the caller is some Flash internal somewhere and it never actually gets to my code because of the errors.

Compiling AS3 quickly

June 24th, 2009

One thing I’ve always missed from my mtasc days is the sheer speed of mtasc. It was almost too fast. Now these days mxmlc provides a similar command line experience, only dirt slow. I suppose Adobe can’t be blamed because it’s due in no small part by Java’s slow startup time, but then again I think I can blame them for that too.

Now, compiling using Flex Builder is faster because the compiler is not unloaded, but it has it’s own problems. In one particular instance I had multiple build targets and experienced even slower speeds than mxmlc alone was capable of. Besides all that, Flex Builder requires a license.

The sole imperfect light on the horizon was fcsh. It only compiles what has changed (crazy! I know!) which makes it extremely fast. The only problem is fcsh is annoying to use and requires that you not leave the program to reap its rewards. There’s also the Flash IDE, and since it’s not really a programmer’s environment, that makes four ways to compile AS3 but no good ways to compile AS3.

Since fcsh has the most promising results I tried to put together a script to manage it, but I couldn’t quite get it to work. Then Ali Rantakari did it with fcshctl. It’s basically what fcsh should’ve been. I’ve had no trouble with multiple build targets, it keeps fcsh running using screen, and the only time it’s ever the slightest bit slow is the first time it compiles something.

So, to save time, I’ve been creating these scripts which make it easy to quickly (re)compile and then launch whatever I’m working on. Here’s an example, which requires fcshctl and flashplayer are in your PATH. If no arguments are given, it will attempt to compile and launch the swf, otherwise it will pass whatever you give it to fcshctl (in case you want to run fcsh commands, like “info”)

#!/bin/bash
if [ -n "$1" ]; then
  fcshctl $@
else
  fcshctl mxmlc 
  -output deploy/target.swf 
  -use-network 
  -compiler.debug 
  src/com/brokenfunction/Target.as 
  -compiler.source-path src && 
  flashplayer deploy/mmvsgng.swf
fi

Despite the fact a lot of this should be unnecessary in the end it’s basically my ideal compilation solution — quick, easy, and customizable. I still keep my ant build files around for my non-debug builds, so they still have a purpose too.

Update: There’s some indication this method no longer works in Flex 4, be careful.

If you use mxmlc and the [Embed] tag you may be aware that you’ve just involved Flex in your project since [Embed] is actually a Flex concept.

Using the “-link-report” option in mxmlc you can see what classes have been compiled into your swf and how much space they use. I found this entry like this in my link report for an [Embed]’d image.

<script name="com/brokenfunction/project/SomeClass_EmbeddedImage.as" mod="1236990005000" size="684" optimizedsize="343">
   <def id="com.brokenfunction.project:SomeClass_EmbeddedImage" />
   <pre id="mx.core:BitmapAsset" />
   <dep id="AS3" />
</script>

See the “mx.core:BitmapAsset” requirement? Since the [Embed]’d asset ends up as a class which extends BitmapAsset it is used even if you don’t use it. I generally just use it as a Bitmap, rather than a BitmapAsset, so it’s largely unnecessary for my needs.

Now, this is all fine, this is how mxmlc does embedding, so it’s necessary. But checking the documentation for BitmapAsset and looking at the link report, we see it’s actually bringing in a bunch of extra classes and interfaces.

<script name="/home/max/bin/flex3/frameworks/libs/framework.swc(mx/core/BitmapAsset)" mod="1224183575340" size="1300" optimizedsize="678">
   <def id="mx.core:BitmapAsset" />
   <pre id="mx.core:IFlexAsset" />
   <pre id="mx.core:FlexBitmap" />
   <pre id="mx.core:IFlexDisplayObject" />
   <dep id="flash.display:BitmapData" />
   <dep id="AS3" />
   <dep id="mx.core:mx_internal" />
</script>

All the “mx” classes are actually compiled into the swf. Now Flex isn’t really bogging down the swf, all in all I found these classes to be around 2k-3k when compressed, but they annoyed me anyway while trying to shrink a preloader for a project. After a lot of Googling I found a solution, but I decided to write a more complete solution here.

You can replace the mx.core.*Asset classes with your own, which replace the originals and remove those unnecessary dependencies. Something like this:

package mx.core {
   import flash.display.Bitmap;
   public class BitmapAsset extends Bitmap {}
}

You can download a collection of these I’ve made here.

I recommend adding them to a new AS3 library, rather than mixing it with any major ones you use, then adding it as another source path for a project.

These could interfere with how classes interact in AS3 if you mix classes using this library and classes that use Flex. Since saving that extra 2k is unnecessary for Flex projects anyway, it’s probably a good idea to use it for AS3-only projects that need to save space.

EDIT 2: swfmill has actually been updated for the first time in about 3 years (wav support included)! An official Windows binary and source code available here. If you’re a Windows user you can skip the stuff about compiling swfmill.

EDIT: Windows swfmill that (apparently) supports wav files available here (thanks rideforever). Just skip straight to working with swfml if you’re using these builds.

Why mxmlc can’t import wav (or any other lossless audio format) files I will never know. Mp3s suffer from timing/looping issues that are easily resolved by using wav files so I’ve always found a way to get my wav files into my swfs. Usually it’s by using the Flash IDE, but I refuse to involve it in my development process anymore.

Other solutions involve parsing wav files, generating swfs on-the-fly, or using Flash 10’s sound api. None really satisfied what I was looking for, compiling them directly into my AS3 code.

I’ve recently discovered a very good solution. It involves compiling a custom version of swfmill with support for wav files then using it to generate swf files. Since any resource inside a swf can be embedded into other swf files using mxmlc, I can then actually import a wav file.

Compiling swfmill

EDIT 2: Like I mentioned above, if you’re a Windows user you can skip this section. Also, if your favorite package manager has swfmill 0.3.0, you can just use that version instead.

This process is intended for Ubuntu, but it’s probably similar to the OSX version if you do the some extra research yourself. As for Windows, you’re on your own, unless you find a way to do it with cygwin.

First, make sure necessary build tools and libraries are available to compile swfmill. On Ubuntu these will do the trick (I think, be sure to comment if you find something is missing):

$ sudo apt-get install build-essential
$ sudo apt-get build-dep swfmill

Next, download the fork of swfmill located here. There’s a download link above the description. It’s a little more advanced than the version available on swfmill.org, in paticular it has support for wav files. Use the latest version of swfmill available here. The lastest version of swfmill will do the trick now. Get it here. Extract it to a folder and compile it.

$ ./autogen.sh
$ make

If anything goes wrong you might be missing some libraries or tools. Use this new new swfmill binary (it’s in the src folder) to compile the upcoming swfml files. Now you can create swf files with wav files in them, but they’re not in your main swf yet.

Using swfmill

This sample swfml file will create a swf file with a single wav file embedded inside (I personally recommend only having one wav file per swf file). Not all wav files will work. only PCM wav files with a frequency of 44100 Hz and below are allowed. Replace “wav_file_to_import” with the location of your wav file and compile.

$ swfmill simple examplesound.swfml examplesound.swf

As an added bonus, it will also play the wav file if you open the swf. Now you can embed the wav file in this swf into your main swf using the embed tag.

[Embed(source='examplesound.swf#importedsound')]
static private const ExampleSound:Class;

public function playSound():void {
  var sound:Sound = new ExampleSound() as Sound;
  sound.play(0, 1);
}

Hope that helps somebody, it’s been a thorn in my side for a long time.

A Nifty AS3 State Trick

January 1st, 2009

I was working on an AS3 class that had a state that needed to be reset every once and a while to some arbitrary original state. It turned out to be an interesting problem. The easy solution of course, is to store the original values into secondary properties and use these values to restore the original state.

public class Example {
  private var _originalX:Number;
  private var _originalY:Number;
  private var _x:Number;
  private var _y:Number;
  public function Example(x:Number, y:Number) {
    _originalX = x;
    _originalY = y;
    reset();
  }
  private function reset():void {
    _x = _originalX;
    _y = _originalY;
  }
  public function doSomething():void {
    reset();
  }
}

Since I was going to do this whole state thing for more classes, and because I felt there had to be an easier way, I went looking for a better solution.

First I thought I could write a function that stored all the properties when called, so it could restore them later. This couldn’t work because not all the properties should be reset. I considered adding a list of properties that should be stored (or not stored), so it would only reset the values I choose.

This solution still seemed imperfect, since creating a large list of state properties was just as annoying as the easy solution, and offered no compiler errors if I made any mistakes. In addition it wouldn’t work for more complex situations like this one.

public class Example extends State {
  private var _rect:Rectangle;
  private var _speed:Number;
  public function Example(rect:Rectangle, speed:Number) {
    _rect = rect;
    _speed = speed;
    // The properties of _rect will not be stored, just the _rect itself
    store("_rect", "_speed");
  }
  public function doSomething():void {
    reset();
    // _rect is unchanged
  }
}

My ideal solution seems so obvious now. It can handle more complex state details, offers nice compiler errors when I make a mistake, and only adds about four extra lines of code to the whole class. Simply use an anonymous function in the constructor as a way of storing the original state so it can be called again later.

public class Example {
  private var _speed:Number;
  private var _rect:Rectangle;
  private var reset:Function;
  public function Example(rect:Rectangle, speed:Number) {
    reset = function():void {
      _rect = rect.clone();// I'm assuming that the original rect doesn't change here
      _speed = speed;
    }
    reset();
  }
  public function doSomething():void {
    reset();
  }
}

I can’t think of many flaws, its main problem is that it does not play well with OOP, since the function must be anonymous and cannot be overridden. Subclasses can still implement this it independently or work together, it’s just not OO by default. It’s probably not going to save any extra memory either, but I wasn’t paticularly concerned about that.

Also, I think it’s important to avoid using the “this” keyword in the anonymous function (or any anonymous function for that matter) since what “this” is can change. For reasons unknown to me, properties accessed without using “this” (like in the example above) always reference the original. Calls however, do not appear to do this.

This could be considered more trouble than its worth, but it didn’t just simplify my code, it turned out to be invaluable as a way to manage the state of the classes I was working with later.

Doom Plays Flash

November 28th, 2008

So, before I could blink, somebody at Newgrounds put together a source port of Doom using Alchemy. Ah well, I was too slow. Through various means I’ve obtained the source code to this port. Mike Welsh, the fellow who created is working on properly releasing the source code. its understandable I suppose, he really did throw it together.

Nonetheless under the powers of the GPL I am providing the thrown together version here if you want it. I haven’t personally compiled it, so you can investigate yourself or wait for Mike’s official version. Good job Mike.

Flash, C/C++ and LLVM

November 18th, 2008

The most interesting thing Adobe has recently announced at Adobe MAX is (easily) Alchemy. It adds some modest support for C/C++ in Flash, but this is still nothing compared to how they did it. Tucked away in the Alchemy FAQ it mentions they used LLVM to do the job. It works by compiling C/C++ to the LLVM instruction set and then converting that to Flash bytecode.

LLVM is intended to act as a medium between a language and an instruction set. If you write a language that compiles to LLVM instructions, you automatically support any instruction set that LLVM supports. If you write a back-end that can understand/convert LLVM instructions, you support any language that compiles to LLVM instructions.

So basically, Adobe may have just opened the door for Python, Java, CIL/.NET languages, and others. I doubt they work right now (I haven’t had the opportunity to try Alchemy yet), and support for Flash’s API would be missing of course, but it appears to be coming.

typeface.js

October 28th, 2008

Embedding fonts in web pages is tricky business. I never really liked the (and let’s face it) hack that has Flash do this job, since Flash can embed fonts. It’s always a little imperfect, since Flash never really integrates fully with web browsers. There’s a CSS way to do it, but apparently it’s spotty.

Hulu is the most popular website I’ve seen use the Flash technique. They use it for the titles of videos since apparently no standard font is capable of displaying it to their needs. Problem is, when you dim the screen, The title of the video doesn’t dim with the rest of the page (at least when I’ve used it). And despite some good effort, it’s basically impossible to highlight Flash and non-Flash text together.

But no more! Now there is typeface.js. It uses canvas (and VML apparently in IE) to draw the fonts directly. Since it’s the browser doing the work in integrates much better into the structure of an HTML document. You can actually highlight the text! Well, not in IE, but I’m betting those users don’t care. And it all fails very gracefully.

Dynamic sound? Meh. 3D? Yawn. Keyboard support in fullscreen mode? Now we’re talking.

You can only use Tab, Space, and the arrow keys though. Tab for jump, space for fire? At least it’s something.