FLASM... stick with me, it could be worth your while.
"flasm is a command line assembler/disassembler of flash actionscript bytecode. flasm 1.41 disassembles your entire SWF including all the timelines, onMovieClip events and button events. After that you are expected to do some optimizations on the disassembled code by hand. flasm replaces then all actions in the original swf with your optimized content...
flasm is not a decompiler! What you get is the human readable representation of swf bytecodes, not actionscript source."
That's the quote from the official site ( http://flasm.sourceforge.net/ ). Don't let "command line", "assembler/disassembler" and "bytecode" put you off!
Firstly I'm going to try and explain how the Flash player handles the action script you write. There's going to be a lot of theory to start with, but once you get it you're well on your way. And even if you never use FLASM it doesn't do any harm to know how things work.
Flash virtual machine:
The computer you are sitting in front of right now. Great isn't it. It let's you play games, listen to music, write novels for threads and you can even look at porn. How much do you know about how it actually works?
You've got a processor, your CPU. This has Registers which are just variables. The CPU stores values in registers and moves them around. That's it. That's all they do.
Each CPU also has it's own instruction set, so for example you can add the contents of registers together ( Exactly the same as a = b + c; ).
The native language of all processors is called machine code and is just a series of 0s and 1s ( On/off, true/false ), but to program in pure machine code is just insane, so all the commands are given mnemonic names. And that's the mythical assembley language, or Assembler.
There is one other important concept I've got to cover before we finish with the CPU. To enable it to keep track of things it needs it has it's own little memory pool all to itself. This is called a Stack. I'll show you why it needs this with a little bit of pseudo action script:
PHP Code:
10 exampleFunction();
20 ...
30 ...
40 function exampleFunction() {
50 trace ("The line numbers will make sense");
60 }
When we write this, the function exampleFunction is called at line 10. So as we know the program will go to line 40 and do whatever. The problem then is that the script has to go back to line 20 to carry on doing what it's meant to be doing. This is where the stack comes in. When a function is called it stores ( Push ) the next line number ( ie 20 ) on the stack, does the function, and then returns back to the line stored on the stack. To stop the stack overflowing the value is removed ( Pop ).
Action script allows stack handling so hopefully this shouldn't be totally alien to you, check your reference.
Onto your operating system. Forget all the icons and windows, they're just gloss to make our lives easier. At the lowest level of all operating systems are routines to allocate memory resources, including screen memory for the display.
So what's all this got to do with the Flash player ? Well the Flash player has registers, it's very own assembler language ( "Bytecode" or "P-Code" ), uses a stack and can allocate memory to itself. In a very simple way the Flash player works like a computer running on top of your real computer, which makes the player a Virtual machine. Thinking of it another way, double click your favourite emulator. That's a virtual machine.
FLASM - assembler/disassembler:
A Disassembler is a program that takes your exe and converts it from machine code into assembley language , or in this case converts your swf into bytecode.
An Assembler ( Note assembley language is often called "Assembler" ( As mentioned above ). It's just another case of one word having two meanings in computer jargon. ) does the opposite, ie converts your bytecode into a swf.
And the point is?:
You've stuck with me this far and I guess some of you are still can't see the point of FLASM. May sound cool, but what's the point ?
When you publish your swf the Flash authoring tool converts all your action script into bytecode, a process known as Compiling ( People who have used C, Java, Pascal et al should be familar with this term ).
No compiling process can ever do the job as well as writing assembler by hand, that's why in really time critical routines people still code in assembler ( Such as the Quake engine ), and that holds true for Flash. By writing in assembler you can speed up your routines, and as game programmers that can't be a bad thing.
I've said this a million times, but here we go... FLASM isn't instant fast forward for your games. By using it you're not going to have a full screen game with eight layers of parallax scrolling. It's not the be all and end all. If you don't want to learn it or just don't get it, don't worry. 99.9% of games get by quite nicely without it :).
If you do learn it and use it you may be able to get another mc running in your game or an extra eye candy effect, without the frame rate dropping.
Right that's way too much in one hit. Let me know what you think of the above ( Too simplistic, too rambling ? ), if there are any errors or bits I've written poorly. I'll go on to setting up FLASM and actually writing bytecode next time.
Phew, now to play with pred's hitTest routine.
Squize.
Part II - Not quite there yet...
Right, we know that the Flash player is a virtual machine with registers and a stack and that it uses a language called bytecode. By coding directly in bytecode you can improve the performance of your swf.
Setting up FLASM:
FLASM is a dos application but someone has written a GUI for it ( http://www.nowrap.de/winflasm.zip ). You can either use that or add FLASM to your right click window, which is the method I prefer. I'm just going to cheat and quote directly from the FLASM site 'cause it's explained well:
"Select View, Folder Options, click the File Types tab, and choose Flash player movie (or similar) type, which stands for swf file extension. Click Edit button, then click New button. In the Action field enter Disassemble. Click the Browse button, navigate to the flasm's folder, and double-click on flasm.exe. No parameters are needed. Click OK, Close, and Close again. Now right click on any swf and choose Disassemble."
You also need to setup the "Update" ( This needs the parameter -u ) command. To test that everything is working find a swf on your hardrive and right click. You should now have the options "Disassemble" and "Update". Pick "Update". A Dos window will appear and then disappear really quickly.
If you look in your folder you should find a new file which will have the extension "$wf". This is a backup of your original swf.
Compare the file size of the backup to the newly updated swf. The swf file should be a couple of bytes smaller.
The update command assembles any FLASM Macros ( More real soon ) and strips out any junk code that Flash puts in when it compiles it. At the very least you should use the update command on ALL your swfs. It takes two seconds, makes the file a bit smaller and removes junk.
Right FLASM is now set-up on your system.
FLASM Macros:
This is the term the author has given to FLASM code embedded directly into your fla. Top tip, you don't even have to worry about this! I'll show you a cool trick where you embed bytecode directly and it's the only time you'll ever have to do it.
Create a new layer in your fla and call it "FLASM". Open up the actions for that layer and enter the following:
PHP Code:
_global.FLASM=false;
$flasm
"push 'FLASM', TRUE"
"setVariable"
$end
So the first line is pure action script, we are just setting the global variable FLASM to false.
The lines "$flasm" and "$end" just tell FLASM that we are embedding a macro. Flash ignores this so you don't have to worry about it screwing up your code.
"push 'FLASM', TRUE"
"setVariable"
Welcome to bytecode!
The "push" command puts values onto the stack ( Which I've done to death already ), so the stack now has the values "FLASM" and "TRUE" on it.
"setVariable" takes the last two values off the stack and makes the first argument the variable name and the second argument is the value to assign to it.
Basically we've just written
FLASM=TRUE;
As I've said Flash ignores anything contained in the "$flasm" and "$end" tags when you publish it, so how does the code run ? When you use the update command ( Using our nice new right click options ) it runs the macro. So in your non-updated swf FLASM=false, but once you update FLASM=true because the macro has been run instead of ignored.
And that's all you'll ever need to know about FLASM Macros.
Real life usage and $include:
When using FLASM you don't disassemble the whole swf because the output file will just be vast and will be near impossible to alter. Trust me on this!
The first thing to decide is what you want to optimize. In an ideal world it would be everything but you would never (Ever) finish your game. Ignore all your init code ( Such as your map plotter, etc. ), it's only run at the start of a game, and for pretty much the same reason ignore the end game stuff ( Do you really need to speed up your "Game Over" screen ? ).
You wanna hit your routines that are run every frame, such as the player routines ( Movement, collision, jump, shoot etc. ) and baddie movement routines. Right break this down even further, the slowest parts are always loops, so you want to hit them first. With loop optimising you want to start at the inner most loop and work out'wards ( Why does the board flag that as a banned word ? ). Why the inner most ? Because it's called the most often. You optimise that and the whole game will run quicker.
So find a function that you want to improve and copy it to a new fla. Save it and publish it so you have a swf with just your function in it. You can now disassemble this using the right click method and you'll find a new file in your folder with the extension ".flm".
Lets pretend our newly disassembled file is called "collisionRoutine.flm". We've done all our optimisations on it ( Part 3 I'm afraid kids ;) ) and we want to include it back into the swf. Just use this simple template:
PHP Code:
function collisionRoutine(){
if (FLASM==true){
$include ("collisionRoutine.flm")
} else {
//The original function
}
}
The "$include" command does just that, loads an external ".flm" file ( Which is just a text file ). This is the FLASM version of #include.
So why do the if (FLASM==true) part ?
Remember that Flash ignores FLASM tags ? We do the check to see if the FLASM varaible is true, if it's not we just run the normal code. Going back to the macro part above, the FLASM var is set to true only if we update the swf, so the $include command is executed only when the swf is updated.
If you didn't have that check and just replaced the whole function with the $include code it would mean that you would have to update the swf every time just to test it, which is just a pain.
So far this has just been boring theory I'm afraid, but you should have everything ready to start the optimisation process and you can even have a play around to see how things work. The next part will be more interesting, we'll get to do a real life example and get our hands dirty with bytecode and register usage. If anyone wants to post a simple example for optimising then that'd be cool.
Squize.