In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: flash player 11 is out

Get Adobe Flash player
by makc3d 24 Oct 2011
  • Forked from wh0's flash player 11 is out
  • Diff: 833
  • Related works: 1
  • Talk

    makc3d at 05 Oct 2011 02:28
    fffuuuuu wmode != direct :(
    makc3d at 05 Oct 2011 13:43
    or even worse, it might require -swf-version=13 :(
    wonderwhyer at 05 Oct 2011 14:47
    Hmm, I wonder when wonderfl will allow that :) Have you seen this already? http://www.youtube.com/watch?feature=player_embedded&v=IykhED4lAWM
    makc3d at 05 Oct 2011 15:47
    they want 25% in royalties, no?
    wonderwhyer at 05 Oct 2011 17:40
    Hmm, I had not personally checked but heard that under some price it is not. Its something like free to use, but if you profit then its 25% of royalties beyond 5k$ So if you have small indie games made once in a few months an earn something like 5k$ each then its completely free :D But I was not speaking about this side of how much it costs to use it, for me it was interesting to see Unreal Tournament 3 working in browser in Flash :) Ouh boy what games we may have soon :D
    esimov at 06 Oct 2011 00:14
    @wonderwhyer I think this is a pretty decent one: http://www.nissan-stagejuk3d.com/
    wonderwhyer at 06 Oct 2011 03:28
    @esimov, you are right, bunch of cool stuff there :) WebGL is cool but its lacking on support/tool chain side, now this here clearly has potential to blow up the web :D
    esimov at 06 Oct 2011 10:08
    @wonderwhyer I think WebGL shouldn't be ignored and has a lot of potential. One major drawback is the lack of standardization among browsers (equally true for javascript).
    wonderwhyer at 06 Oct 2011 12:52
    I am not saying we should ignore it. Just feels that its not there yet and no one knows when it will be. Its one thing to play with it in small projects but big guys like Epic just don't know from which side to plug it yet. Its AAA not ready so to say. And yeah, biggest problem is consistency between browsers. What works in FF not always works in Chrome and IE so far ignores it completely. But in what Epic did, they can't do it for HTML/JS/WebGL for another reason too. Flash has Alchemy to compile C++ in to Flash ABC. How do you compile C++ in to JS? JS is too far from real OOP and lot of low level things to allow that currently. Though I guess C++ => Java => JS is possible but for not very broad code base.
    esimov at 06 Oct 2011 14:02
    With the v.11 Flash definitely became a true player in 3D competition, the only concern which argue against him is how much developers will stick with it, considering the huge performance boost Javascript benefits with and definitely the openness, which cannot be said about Flash. And one more positive aspect for WebGL is it's wide penetration between developers. I'm completely agree that HTML5 at the moment is not offering a true gaming experience, but this is the new star :)...and as someone said if you are not interested in 3D then this is the time to migrate to JS. This is not my case...i'm only lobbying for openness.
    wonderwhyer at 06 Oct 2011 16:24
    I can't agree really. Am playing with HTML5/CSS3/JS for half a year, actually my story starts 6-7 years ago when was starting to learn HTML and Flash in parallel and quickly switched to Flash only, HTML was a mess back then and is still. Soo am playing HTML5/CSS3 and some Python and PHP. And I must say that HTML5/CSS3/JS are still green. They are good for small stuff. You can write complex client side multimedia things on them well. It feels like you are hacking around limitations of technology all the time. It lacks some consistency, and I am not speaking about browsers even, its overall.
    wonderwhyer at 06 Oct 2011 16:24
    Like they say about JS that its lot of crap with some very good stuff, you need to know what crap is and what good is and try to use only good stuff. That's how all HTML5/CSS3/JS feels to me right now. Its one thing to do simple stylish pages and banners on them but writing couple of dozen of thousands of lines of code for a game in team of 10 people half of which are not JS gurus? Forget it, it will be a nightmare. Feels like technology just can't really efficiently sustain such projects. And that's where Flash will still come in. While HTML5/CSS3/JS will eat in to banners, small brand sites, and just overall improve look and feel of the web. Complex RIA will for some time stay in Flash unless you want to target iOS in browser.
    wonderwhyer at 06 Oct 2011 16:25
    But that's my two cents, and I am very green with HTML5/CSS3/JS and may be wrong, just my feelings of learning it. But in comparison to my experience 6-7 years back, it got a lot better. I can do pretty interfaces without images at last. Still need to hack and do dirty work(work not worthy of a man) with HTML/CSS to do it but at least I can now. But a lot is still left to wish for :( In the end, right tool for the right job. Something big, multimedia, in browser, iOS not necessary, client side = Flash. Simple and functional on front end, usable sites, banners, iOS in browser etc = HTML.
    wonderwhyer at 06 Oct 2011 16:25
    Also I have doubts that Flash or plugins will die out ever. HTML5 is standard, its lowest ubiquitous level everyone who wants to be part of the web should provide(browser makers). Its kind of like already tried, approved, polished things. While plugins in specification exist as one of forefronts where anyone tries new things not possible in current standard, and if they work, catch on, people like and use it, standard starts to include it. That's what is happening now, HTML5 eats away lot of what Flash was doing and trying for years and it was working and people used it, now Flash or any other plugin should start looking for new "fronts" of where web could go and what it could do. Killing plugins would slow down exploration of new things a lot.
    wonderwhyer at 06 Oct 2011 16:25
    Damn my comment got big :D Wall of text :(
    esimov at 06 Oct 2011 22:31
    No problem, glad You developed your opinion :) BTW: http://www.next-gen.biz/news/crytek-investigating-flash-support-cryengine
    wonderwhyer at 06 Oct 2011 23:59
    Heh, my thoughts were "Now out of sense of competition CryTech will need to join the show" :) Did not hear they were making their plugin already. Though EA playing in that market for a while already with their own plugin in BattleFiedl Heroes and Battlefield Play for Free.
    makc3d at 24 Oct 2011 02:57
    ok, sorted swf-version=13 is fixed :) [ErrorEvent type="error" bubbles=false cancelable=false eventPhase=2 text="Error #3702: Context3D not available."] I guess it's wmode=direct, that only wonderfl guys can help with :(
    yonatan at 24 Oct 2011 03:43
    you can select the wmode when you edit, it's next to the related images uploader.
    Embed
/**
 * Copyright makc3d ( http://wonderfl.net/user/makc3d )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6cHq
 */

// forked from wh0's flash player 11 is out
package {
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
    public class FlashTest extends Sprite {

		// based on Adobe's example :)
        public function FlashTest () {
			if (loaderInfo.bytes [3] != 13) {
				var bytes:ByteArray = loaderInfo.bytes;
				bytes [3] = 13;
				var loader:Loader = new Loader;
				addChild (loader);
				loader.loadBytes (bytes);
			} else {
				if (stage) {
					init ();
				} else {
					addEventListener (Event.ADDED_TO_STAGE, init);
				}
			}
		}

		public function init ():void {
			var stage3D:* = stage ["stage3Ds"] [0];
			stage3D.addEventListener ("context3DCreate", yay);
			stage3D.addEventListener (ErrorEvent.ERROR, fuck);
			stage3D.requestContext3D ();
        }

		public function fuck (e:ErrorEvent):void {
			var tf:TextField = new TextField;
			tf.autoSize = "left";
			tf.text = e.toString ();
			addChild (tf);
		}

		public var fragmentShaderAssembler:AGALMiniAssembler;
		public var vertexShaderAssembler:AGALMiniAssembler;

		public var context3D:*;

		public var shaderProgram:*//Program3D;
		public var indexBuffer:*//IndexBuffer3D;
		public var vertexBuffer:*//VertexBuffer3D;

		public function yay (e:Event):void {
			var stage3D:* = e.target;

			context3D = stage3D.context3D;
			context3D.configureBackBuffer (465, 465, 0, true);

			vertexShaderAssembler = new AGALMiniAssembler();
			vertexShaderAssembler.assemble ("vertex",
				"dp4 op.x, va0, vc0		\n" +	// 4x4 matrix transform from stream 0 to output clipspace
				"dp4 op.y, va0, vc1		\n" +
				"dp4 op.z, va0, vc2		\n" +
				"dp4 op.w, va0, vc3		\n" +
				"mov v0, va1.xyzw		\n"	// copy texcoord from stream 1 to fragment program
			);

			fragmentShaderAssembler = new AGALMiniAssembler(); 
			fragmentShaderAssembler.assemble ("fragment",
				"mov oc, v0" /* copy color */
			);

			shaderProgram = context3D.createProgram();
			shaderProgram.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode );			

			indexBuffer = context3D.createIndexBuffer( 3 );
			indexBuffer.uploadFromVector( Vector.<uint>( [ 0, 1, 2 ] ), 0, 3 );  			 			
			vertexBuffer = context3D.createVertexBuffer( 3, 5 ); // 3 vertices, 5 floats per vertex
			vertexBuffer.uploadFromVector(
				Vector.<Number>(
					[
						// x,y, r,g,b format
						-1,-1, 0,1,0,
						0,1,  1,0,0,
						1,-1, 0,0,1
					]
				),
				0, 3
			);

			addEventListener (Event.ENTER_FRAME, loop);
		}

		public function loop (e:Event):void {
			var t:Number = getTimer() / 1000;
			var a:Number = Math.sin( t / 2 ) * .5 + .5; 
			context3D.clear( 0, a, 0, a );

			context3D.setProgram( shaderProgram );
			context3D.setVertexBufferAt( 0, vertexBuffer, 0, "float2");
			context3D.setVertexBufferAt( 1, vertexBuffer, 2, "float3");
		
			var matrix:Matrix3D = new Matrix3D;
			matrix.appendRotation( t * 20, Vector3D.Z_AXIS );
			context3D.setProgramConstantsFromMatrix("vertex", 0, matrix, true );
			context3D.drawTriangles( indexBuffer, 0, 1 );
		
			context3D.present();
		}
    }
}


// ================================================================================
//
//	ADOBE SYSTEMS INCORPORATED
//	Copyright 2010 Adobe Systems Incorporated
//	All Rights Reserved.
//
//	NOTICE: Adobe permits you to use, modify, and distribute this file
//	in accordance with the terms of the license agreement accompanying it.
//
// ================================================================================
/*package com.adobe.utils*/
{
	// ===========================================================================
	//	Imports
	// ---------------------------------------------------------------------------
	//import flash.display3D.*;
	import flash.utils.*;
	
	// ===========================================================================
	//	Class
	// ---------------------------------------------------------------------------
	/*public*/ class AGALMiniAssembler
	{
		// ======================================================================
		//	Properties
		// ----------------------------------------------------------------------
		// AGAL bytes and error buffer 
		private var _agalcode:ByteArray							= null;
		private var _error:String								= "";
		
		private var debugEnabled:Boolean						= false;
		
		private static var initialized:Boolean					= false;
		
		// ======================================================================
		//	Getters
		// ----------------------------------------------------------------------
		public function get error():String						{ return _error; }
		public function get agalcode():ByteArray				{ return _agalcode; }
		
		// ======================================================================
		//	Constructor
		// ----------------------------------------------------------------------
		public function AGALMiniAssembler( debugging:Boolean = false ):void
		{
			debugEnabled = debugging;
			if ( !initialized )
				init();
		}
		// ======================================================================
		//	Methods
		// ----------------------------------------------------------------------
		public function assemble( mode:String, source:String, verbose:Boolean = false ):ByteArray
		{
			var start:uint = getTimer();
			
			_agalcode = new ByteArray();			
			_error = "";
			
			var isFrag:Boolean = false;
			
			if ( mode == FRAGMENT )
				isFrag = true
			else if ( mode != VERTEX )
				_error = 'ERROR: mode needs to be "' + FRAGMENT + '" or "' + VERTEX + '" but is "' + mode + '".';
			
			agalcode.endian = Endian.LITTLE_ENDIAN;
			agalcode.writeByte( 0xa0 );				// tag version
			agalcode.writeUnsignedInt( 0x1 );		// AGAL version, big endian, bit pattern will be 0x01000000
			agalcode.writeByte( 0xa1 );				// tag program id
			agalcode.writeByte( isFrag ? 1 : 0 );	// vertex or fragment
			
			var lines:Array = source.replace( /[\f\n\r\v]+/g, "\n" ).split( "\n" );
			var nest:int = 0;
			var nops:int = 0;
			var i:int;
			var lng:int = lines.length;
			
			for ( i = 0; i < lng && _error == ""; i++ )
			{
				var line:String = new String( lines[i] );
				
				// remove comments
				var startcomment:int = line.search( "//" );
				if ( startcomment != -1 )
					line = line.slice( 0, startcomment );
				
				// grab options
				var optsi:int = line.search( /<.*>/g );
				var opts:Array;
				if ( optsi != -1 )
				{
					opts = line.slice( optsi ).match( /([\w\.\-\+]+)/gi );
					line = line.slice( 0, optsi );
				}
				
				// find opcode
				var opCode:Array = line.match( /^\w{3}/ig );
				var opFound:OpCode = OPMAP[ opCode[0] ];
				
				// if debug is enabled, output the opcodes
				if ( debugEnabled )
					trace( opFound );
				
				if ( opFound == null )
				{
					if ( line.length >= 3 )
						trace( "warning: bad line "+i+": "+lines[i] );
					continue;
				}
				
				line = line.slice( line.search( opFound.name ) + opFound.name.length );
				
				// nesting check
				if ( opFound.flags & OP_DEC_NEST )
				{
					nest--;
					if ( nest < 0 )
					{
						_error = "error: conditional closes without open.";
						break;
					}
				}
				if ( opFound.flags & OP_INC_NEST )
				{
					nest++;
					if ( nest > MAX_NESTING )
					{
						_error = "error: nesting to deep, maximum allowed is "+MAX_NESTING+".";
						break;
					}
				}
				if ( ( opFound.flags & OP_FRAG_ONLY ) && !isFrag )
				{
					_error = "error: opcode is only allowed in fragment programs.";
					break;
				}
				if ( verbose )
					trace( "emit opcode=" + opFound );
				
				agalcode.writeUnsignedInt( opFound.emitCode );
				nops++;
				
				if ( nops > MAX_OPCODES )
				{
					_error = "error: too many opcodes. maximum is "+MAX_OPCODES+".";
					break;
				}
				
				// get operands, use regexp
				var regs:Array = line.match( /vc\[([vof][actps]?)(\d*)?(\.[xyzw](\+\d{1,3})?)?\](\.[xyzw]{1,4})?|([vof][actps]?)(\d*)?(\.[xyzw]{1,4})?/gi );
				if ( regs.length != opFound.numRegister )
				{
					_error = "error: wrong number of operands. found "+regs.length+" but expected "+opFound.numRegister+".";
					break;
				}
				
				var badreg:Boolean	= false;
				var pad:uint		= 64 + 64 + 32;
				var regLength:uint	= regs.length;
				
				for ( var j:int = 0; j < regLength; j++ )
				{
					var isRelative:Boolean = false;
					var relreg:Array = regs[ j ].match( /\[.*\]/ig );
					if ( relreg.length > 0 )
					{
						regs[ j ] = regs[ j ].replace( relreg[ 0 ], "0" );
						
						if ( verbose )
							trace( "IS REL" );
						isRelative = true;
					}
					
					var res:Array = regs[j].match( /^\b[A-Za-z]{1,2}/ig );
					var regFound:Register = REGMAP[ res[ 0 ] ];
					
					// if debug is enabled, output the registers
					if ( debugEnabled )
						trace( regFound );
					
					if ( regFound == null )
					{
						_error = "error: could not parse operand "+j+" ("+regs[j]+").";
						badreg = true;
						break;
					}
					
					if ( isFrag )
					{
						if ( !( regFound.flags & REG_FRAG ) )
						{
							_error = "error: register operand "+j+" ("+regs[j]+") only allowed in vertex programs.";
							badreg = true;
							break;
						}
						if ( isRelative )
						{
							_error = "error: register operand "+j+" ("+regs[j]+") relative adressing not allowed in fragment programs.";
							badreg = true;
							break;
						}			
					}
					else
					{
						if ( !( regFound.flags & REG_VERT ) )
						{
							_error = "error: register operand "+j+" ("+regs[j]+") only allowed in fragment programs.";
							badreg = true;
							break;
						}
					}
					
					regs[j] = regs[j].slice( regs[j].search( regFound.name ) + regFound.name.length );
					//trace( "REGNUM: " +regs[j] );
					var idxmatch:Array = isRelative ? relreg[0].match( /\d+/ ) : regs[j].match( /\d+/ );
					var regidx:uint = 0;
					
					if ( idxmatch )
						regidx = uint( idxmatch[0] );
					
					if ( regFound.range < regidx )
					{
						_error = "error: register operand "+j+" ("+regs[j]+") index exceeds limit of "+(regFound.range+1)+".";
						badreg = true;
						break;
					}
					
					var regmask:uint		= 0;
					var maskmatch:Array		= regs[j].match( /(\.[xyzw]{1,4})/ );
					var isDest:Boolean		= ( j == 0 && !( opFound.flags & OP_NO_DEST ) );
					var isSampler:Boolean	= ( j == 2 && ( opFound.flags & OP_SPECIAL_TEX ) );
					var reltype:uint		= 0;
					var relsel:uint			= 0;
					var reloffset:int		= 0;
					
					if ( isDest && isRelative )
					{
						_error = "error: relative can not be destination";	
						badreg = true; 
						break;								
					}
					
					if ( maskmatch )
					{
						regmask = 0;
						var cv:uint; 
						var maskLength:uint = maskmatch[0].length;
						for ( var k:int = 1; k < maskLength; k++ )
						{
							cv = maskmatch[0].charCodeAt(k) - "x".charCodeAt(0);
							if ( cv > 2 )
								cv = 3;
							if ( isDest )
								regmask |= 1 << cv;
							else
								regmask |= cv << ( ( k - 1 ) << 1 );
						}
						if ( !isDest )
							for ( ; k <= 4; k++ )
								regmask |= cv << ( ( k - 1 ) << 1 ) // repeat last								
					}
					else
					{
						regmask = isDest ? 0xf : 0xe4; // id swizzle or mask						
					}
					
					if ( isRelative )
					{
						var relname:Array = relreg[0].match( /[A-Za-z]{1,2}/ig );						
						var regFoundRel:Register = REGMAP[ relname[0]];						
						if ( regFoundRel == null )
						{ 
							_error = "error: bad index register"; 
							badreg = true; 
							break;
						}
						reltype = regFoundRel.emitCode;
						var selmatch:Array = relreg[0].match( /(\.[xyzw]{1,1})/ );						
						if ( selmatch.length==0 )
						{
							_error = "error: bad index register select"; 
							badreg = true; 
							break;						
						}
						relsel = selmatch[0].charCodeAt(1) - "x".charCodeAt(0);
						if ( relsel > 2 )
							relsel = 3; 
						var relofs:Array = relreg[0].match( /\+\d{1,3}/ig );
						if ( relofs.length > 0 ) 
							reloffset = relofs[0]; 						
						if ( reloffset < 0 || reloffset > 255 )
						{
							_error = "error: index offset "+reloffset+" out of bounds. [0..255]"; 
							badreg = true; 
							break;							
						}
						if ( verbose )
							trace( "RELATIVE: type="+reltype+"=="+relname[0]+" sel="+relsel+"=="+selmatch[0]+" idx="+regidx+" offset="+reloffset ); 
					}
					
					if ( verbose )
						trace( "  emit argcode="+regFound+"["+regidx+"]["+regmask+"]" );
					if ( isDest )
					{												
						agalcode.writeShort( regidx );
						agalcode.writeByte( regmask );
						agalcode.writeByte( regFound.emitCode );
						pad -= 32; 
					} else
					{
						if ( isSampler )
						{
							if ( verbose )
								trace( "  emit sampler" );
							var samplerbits:uint = 5; // type 5 
							var optsLength:uint = opts.length;
							var bias:Number = 0; 
							for ( k = 0; k<optsLength; k++ )
							{
								if ( verbose )
									trace( "    opt: "+opts[k] );
								var optfound:Sampler = SAMPLEMAP [opts[k]];
								if ( optfound == null )
								{
									// todo check that it's a number...
									//trace( "Warning, unknown sampler option: "+opts[k] );
									bias = Number(opts[k]); 
									if ( verbose )
										trace( "    bias: " + bias );																	
								}
								else
								{
									if ( optfound.flag != SAMPLER_SPECIAL_SHIFT )
										samplerbits &= ~( 0xf << optfound.flag );										
									samplerbits |= uint( optfound.mask ) << uint( optfound.flag );
								}
							}
							agalcode.writeShort( regidx );
							agalcode.writeByte(int(bias*8.0));
							agalcode.writeByte(0);							
							agalcode.writeUnsignedInt( samplerbits );
							
							if ( verbose )
								trace( "    bits: " + ( samplerbits - 5 ) );
							pad -= 64;
						}
						else
						{
							if ( j == 0 )
							{
								agalcode.writeUnsignedInt( 0 );
								pad -= 32;
							}
							agalcode.writeShort( regidx );
							agalcode.writeByte( reloffset );
							agalcode.writeByte( regmask );
							agalcode.writeByte( regFound.emitCode );
							agalcode.writeByte( reltype );
							agalcode.writeShort( isRelative ? ( relsel | ( 1 << 15 ) ) : 0 );
							
							pad -= 64;
						}
					}
				}
				
				// pad unused regs
				for ( j = 0; j < pad; j += 8 ) 
					agalcode.writeByte( 0 );
				
				if ( badreg )
					break;
			}
			
			if ( _error != "" )
			{
				_error += "\n  at line " + i + " " + lines[i];
				agalcode.length = 0;
				trace( _error );
			}
			
			// trace the bytecode bytes if debugging is enabled
			if ( debugEnabled )
			{
				var dbgLine:String = "generated bytecode:";
				var agalLength:uint = agalcode.length;
				for ( var index:uint = 0; index < agalLength; index++ )
				{
					if ( !( index % 16 ) )
						dbgLine += "\n";
					if ( !( index % 4 ) )
						dbgLine += " ";
					
					var byteStr:String = agalcode[ index ].toString( 16 );
					if ( byteStr.length < 2 )
						byteStr = "0" + byteStr;
					
					dbgLine += byteStr;
				}
				trace( dbgLine );
			}
			
			if ( verbose )
				trace( "AGALMiniAssembler.assemble time: " + ( ( getTimer() - start ) / 1000 ) + "s" );
			
			return agalcode;
		}
		
		static private function init():void
		{
			initialized = true;
			
			// Fill the dictionaries with opcodes and registers
			OPMAP[ MOV ] = new OpCode( MOV, 2, 0x00, 0 );
			OPMAP[ ADD ] = new OpCode( ADD, 3, 0x01, 0 );
			OPMAP[ SUB ] = new OpCode( SUB, 3, 0x02, 0 );
			OPMAP[ MUL ] = new OpCode( MUL, 3, 0x03, 0 );
			OPMAP[ DIV ] = new OpCode( DIV, 3, 0x04, 0 );
			OPMAP[ RCP ] = new OpCode( RCP, 2, 0x05, 0 );					
			OPMAP[ MIN ] = new OpCode( MIN, 3, 0x06, 0 );
			OPMAP[ MAX ] = new OpCode( MAX, 3, 0x07, 0 );
			OPMAP[ FRC ] = new OpCode( FRC, 2, 0x08, 0 );			
			OPMAP[ SQT ] = new OpCode( SQT, 2, 0x09, 0 );
			OPMAP[ RSQ ] = new OpCode( RSQ, 2, 0x0a, 0 );
			OPMAP[ POW ] = new OpCode( POW, 3, 0x0b, 0 );
			OPMAP[ LOG ] = new OpCode( LOG, 2, 0x0c, 0 );
			OPMAP[ EXP ] = new OpCode( EXP, 2, 0x0d, 0 );
			OPMAP[ NRM ] = new OpCode( NRM, 2, 0x0e, 0 );
			OPMAP[ SIN ] = new OpCode( SIN, 2, 0x0f, 0 );
			OPMAP[ COS ] = new OpCode( COS, 2, 0x10, 0 );
			OPMAP[ CRS ] = new OpCode( CRS, 3, 0x11, 0 );
			OPMAP[ DP3 ] = new OpCode( DP3, 3, 0x12, 0 );
			OPMAP[ DP4 ] = new OpCode( DP4, 3, 0x13, 0 );					
			OPMAP[ ABS ] = new OpCode( ABS, 2, 0x14, 0 );
			OPMAP[ NEG ] = new OpCode( NEG, 2, 0x15, 0 );
			OPMAP[ SAT ] = new OpCode( SAT, 2, 0x16, 0 );
			OPMAP[ M33 ] = new OpCode( M33, 3, 0x17, OP_SPECIAL_MATRIX );
			OPMAP[ M44 ] = new OpCode( M44, 3, 0x18, OP_SPECIAL_MATRIX );
			OPMAP[ M34 ] = new OpCode( M34, 3, 0x19, OP_SPECIAL_MATRIX );			
			OPMAP[ IFZ ] = new OpCode( IFZ, 1, 0x1a, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ INZ ] = new OpCode( INZ, 1, 0x1b, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ IFE ] = new OpCode( IFE, 2, 0x1c, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ INE ] = new OpCode( INE, 2, 0x1d, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ IFG ] = new OpCode( IFG, 2, 0x1e, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ IFL ] = new OpCode( IFL, 2, 0x1f, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ IEG ] = new OpCode( IEG, 2, 0x20, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ IEL ] = new OpCode( IEL, 2, 0x21, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ ELS ] = new OpCode( ELS, 0, 0x22, OP_NO_DEST | OP_INC_NEST | OP_DEC_NEST );
			OPMAP[ EIF ] = new OpCode( EIF, 0, 0x23, OP_NO_DEST | OP_DEC_NEST );
			OPMAP[ REP ] = new OpCode( REP, 1, 0x24, OP_NO_DEST | OP_INC_NEST | OP_SCALAR );
			OPMAP[ ERP ] = new OpCode( ERP, 0, 0x25, OP_NO_DEST | OP_DEC_NEST );
			OPMAP[ BRK ] = new OpCode( BRK, 0, 0x26, OP_NO_DEST );
			OPMAP[ KIL ] = new OpCode( KIL, 1, 0x27, OP_NO_DEST | OP_FRAG_ONLY );
			OPMAP[ TEX ] = new OpCode( TEX, 3, 0x28, OP_FRAG_ONLY | OP_SPECIAL_TEX );
			OPMAP[ SGE ] = new OpCode( SGE, 3, 0x29, 0 );
			OPMAP[ SLT ] = new OpCode( SLT, 3, 0x2a, 0 );
			OPMAP[ SGN ] = new OpCode( SGN, 2, 0x2b, 0 );
			
			REGMAP[ VA ]	= new Register( VA,	"vertex attribute",		0x0,	7,		REG_VERT | REG_READ );
			REGMAP[ VC ]	= new Register( VC,	"vertex constant",		0x1,	127,	REG_VERT | REG_READ );
			REGMAP[ VT ]	= new Register( VT,	"vertex temporary",		0x2,	7,		REG_VERT | REG_WRITE | REG_READ );
			REGMAP[ OP ]	= new Register( OP,	"vertex output",		0x3,	0,		REG_VERT | REG_WRITE );
			REGMAP[ V ]		= new Register( V,	"varying",				0x4,	7,		REG_VERT | REG_FRAG | REG_READ | REG_WRITE );
			REGMAP[ FC ]	= new Register( FC,	"fragment constant",	0x1,	27,		REG_FRAG | REG_READ );
			REGMAP[ FT ]	= new Register( FT,	"fragment temporary",	0x2,	7,		REG_FRAG | REG_WRITE | REG_READ );
			REGMAP[ FS ]	= new Register( FS,	"texture sampler",		0x5,	7,		REG_FRAG | REG_READ );
			REGMAP[ OC ]	= new Register( OC,	"fragment output",		0x3,	0,		REG_FRAG | REG_WRITE );
			
			SAMPLEMAP[ D2 ]			= new Sampler( D2,			SAMPLER_DIM_SHIFT,		0 );
			SAMPLEMAP[ D3 ]			= new Sampler( D3,			SAMPLER_DIM_SHIFT,		2 );
			SAMPLEMAP[ CUBE ]		= new Sampler( CUBE,		SAMPLER_DIM_SHIFT,		1 );
			SAMPLEMAP[ MIPNEAREST ]	= new Sampler( MIPNEAREST,	SAMPLER_MIPMAP_SHIFT,	1 );
			SAMPLEMAP[ MIPLINEAR ]	= new Sampler( MIPLINEAR,	SAMPLER_MIPMAP_SHIFT,	2 );
			SAMPLEMAP[ MIPNONE ]	= new Sampler( MIPNONE,		SAMPLER_MIPMAP_SHIFT,	0 );
			SAMPLEMAP[ NOMIP ]		= new Sampler( NOMIP,		SAMPLER_MIPMAP_SHIFT,	0 );
			SAMPLEMAP[ NEAREST ]	= new Sampler( NEAREST,		SAMPLER_FILTER_SHIFT,	0 );
			SAMPLEMAP[ LINEAR ]		= new Sampler( LINEAR,		SAMPLER_FILTER_SHIFT,	1 );
			SAMPLEMAP[ CENTROID ]	= new Sampler( CENTROID,	SAMPLER_SPECIAL_SHIFT,	1 << 0 );
			SAMPLEMAP[ SINGLE ]		= new Sampler( SINGLE,		SAMPLER_SPECIAL_SHIFT,	1 << 1 );
			SAMPLEMAP[ DEPTH ]		= new Sampler( DEPTH,		SAMPLER_SPECIAL_SHIFT,	1 << 2 );
			SAMPLEMAP[ REPEAT ]		= new Sampler( REPEAT,		SAMPLER_REPEAT_SHIFT,	1 );
			SAMPLEMAP[ WRAP ]		= new Sampler( WRAP,		SAMPLER_REPEAT_SHIFT,	1 );
			SAMPLEMAP[ CLAMP ]		= new Sampler( CLAMP,		SAMPLER_REPEAT_SHIFT,	0 );
		}
		
		// ======================================================================
		//	Constants
		// ----------------------------------------------------------------------
		private static const OPMAP:Dictionary					= new Dictionary();
		private static const REGMAP:Dictionary					= new Dictionary();
		private static const SAMPLEMAP:Dictionary				= new Dictionary();
		
		private static const MAX_NESTING:int					= 4;
		private static const MAX_OPCODES:int					= 256;
		
		private static const FRAGMENT:String					= "fragment";
		private static const VERTEX:String						= "vertex";
		
		// masks and shifts
		private static const SAMPLER_DIM_SHIFT:uint				= 12;
		private static const SAMPLER_SPECIAL_SHIFT:uint			= 16;
		private static const SAMPLER_REPEAT_SHIFT:uint			= 20;
		private static const SAMPLER_MIPMAP_SHIFT:uint			= 24;
		private static const SAMPLER_FILTER_SHIFT:uint			= 28;
		
		// regmap flags
		private static const REG_WRITE:uint						= 0x1;
		private static const REG_READ:uint						= 0x2;
		private static const REG_FRAG:uint						= 0x20;
		private static const REG_VERT:uint						= 0x40;
		
		// opmap flags
		private static const OP_SCALAR:uint						= 0x1;
		private static const OP_INC_NEST:uint					= 0x2;
		private static const OP_DEC_NEST:uint					= 0x4;
		private static const OP_SPECIAL_TEX:uint				= 0x8;
		private static const OP_SPECIAL_MATRIX:uint				= 0x10;
		private static const OP_FRAG_ONLY:uint					= 0x20;
		private static const OP_VERT_ONLY:uint					= 0x40;
		private static const OP_NO_DEST:uint					= 0x80;
		
		// opcodes
		private static const MOV:String							= "mov";
		private static const ADD:String							= "add";
		private static const SUB:String							= "sub";
		private static const MUL:String							= "mul";
		private static const DIV:String							= "div";
		private static const RCP:String							= "rcp";
		private static const MIN:String							= "min";
		private static const MAX:String							= "max";
		private static const FRC:String							= "frc";
		private static const SQT:String							= "sqt";
		private static const RSQ:String							= "rsq";
		private static const POW:String							= "pow";
		private static const LOG:String							= "log";
		private static const EXP:String							= "exp";
		private static const NRM:String							= "nrm";
		private static const SIN:String							= "sin";
		private static const COS:String							= "cos";
		private static const CRS:String							= "crs";
		private static const DP3:String							= "dp3";
		private static const DP4:String							= "dp4";
		private static const ABS:String							= "abs";
		private static const NEG:String							= "neg";
		private static const SAT:String							= "sat";
		private static const M33:String							= "m33";
		private static const M44:String							= "m44";
		private static const M34:String							= "m34";
		private static const IFZ:String							= "ifz";
		private static const INZ:String							= "inz";
		private static const IFE:String							= "ife";
		private static const INE:String							= "ine";
		private static const IFG:String							= "ifg";
		private static const IFL:String							= "ifl";
		private static const IEG:String							= "ieg";
		private static const IEL:String							= "iel";
		private static const ELS:String							= "els";
		private static const EIF:String							= "eif";
		private static const REP:String							= "rep";
		private static const ERP:String							= "erp";
		private static const BRK:String							= "brk";
		private static const KIL:String							= "kil";
		private static const TEX:String							= "tex";
		private static const SGE:String							= "sge";
		private static const SLT:String							= "slt";
		private static const SGN:String							= "sgn";
		
		// registers
		private static const VA:String							= "va";
		private static const VC:String							= "vc";
		private static const VT:String							= "vt";
		private static const OP:String							= "op";
		private static const V:String							= "v";
		private static const FC:String							= "fc";
		private static const FT:String							= "ft";
		private static const FS:String							= "fs";
		private static const OC:String							= "oc";
		
		// samplers
		private static const D2:String							= "2d";
		private static const D3:String							= "3d";
		private static const CUBE:String						= "cube";
		private static const MIPNEAREST:String					= "mipnearest";
		private static const MIPLINEAR:String					= "miplinear";
		private static const MIPNONE:String						= "mipnone";
		private static const NOMIP:String						= "nomip";
		private static const NEAREST:String						= "nearest";
		private static const LINEAR:String						= "linear";
		private static const CENTROID:String					= "centroid";
		private static const SINGLE:String						= "single";
		private static const DEPTH:String						= "depth";
		private static const REPEAT:String						= "repeat";
		private static const WRAP:String						= "wrap";
		private static const CLAMP:String						= "clamp";
	}
}

// ================================================================================
//	Helper Classes
// --------------------------------------------------------------------------------
{
	// ===========================================================================
	//	Class
	// ---------------------------------------------------------------------------
	class OpCode
	{		
		// ======================================================================
		//	Properties
		// ----------------------------------------------------------------------
		private var _emitCode:uint;
		private var _flags:uint;
		private var _name:String;
		private var _numRegister:uint;
		
		// ======================================================================
		//	Getters
		// ----------------------------------------------------------------------
		public function get emitCode():uint		{ return _emitCode; }
		public function get flags():uint		{ return _flags; }
		public function get name():String		{ return _name; }
		public function get numRegister():uint	{ return _numRegister; }
		
		// ======================================================================
		//	Constructor
		// ----------------------------------------------------------------------
		public function OpCode( name:String, numRegister:uint, emitCode:uint, flags:uint)
		{
			_name = name;
			_numRegister = numRegister;
			_emitCode = emitCode;
			_flags = flags;
		}		
		
		// ======================================================================
		//	Methods
		// ----------------------------------------------------------------------
		public function toString():String
		{
			return "[OpCode name=\""+_name+"\", numRegister="+_numRegister+", emitCode="+_emitCode+", flags="+_flags+"]";
		}
	}
	
	// ===========================================================================
	//	Class
	// ---------------------------------------------------------------------------
	class Register
	{
		// ======================================================================
		//	Properties
		// ----------------------------------------------------------------------
		private var _emitCode:uint;
		private var _name:String;
		private var _longName:String;
		private var _flags:uint;
		private var _range:uint;
		
		// ======================================================================
		//	Getters
		// ----------------------------------------------------------------------
		public function get emitCode():uint		{ return _emitCode; }
		public function get longName():String	{ return _longName; }
		public function get name():String		{ return _name; }
		public function get flags():uint		{ return _flags; }
		public function get range():uint		{ return _range; }
		
		// ======================================================================
		//	Constructor
		// ----------------------------------------------------------------------
		public function Register( name:String, longName:String, emitCode:uint, range:uint, flags:uint)
		{
			_name = name;
			_longName = longName;
			_emitCode = emitCode;
			_range = range;
			_flags = flags;
		}
		
		// ======================================================================
		//	Methods
		// ----------------------------------------------------------------------
		public function toString():String
		{
			return "[Register name=\""+_name+"\", longName=\""+_longName+"\", emitCode="+_emitCode+", range="+_range+", flags="+ _flags+"]";
		}
	}
	
	// ===========================================================================
	//	Class
	// ---------------------------------------------------------------------------
	class Sampler
	{
		// ======================================================================
		//	Properties
		// ----------------------------------------------------------------------
		private var _flag:uint;
		private var _mask:uint;
		private var _name:String;
		
		// ======================================================================
		//	Getters
		// ----------------------------------------------------------------------
		public function get flag():uint		{ return _flag; }
		public function get mask():uint		{ return _mask; }
		public function get name():String	{ return _name; }
		
		// ======================================================================
		//	Constructor
		// ----------------------------------------------------------------------
		public function Sampler( name:String, flag:uint, mask:uint )
		{
			_name = name;
			_flag = flag;
			_mask = mask;
		}
		
		// ======================================================================
		//	Methods
		// ----------------------------------------------------------------------
		public function toString():String
		{
			return "[Sampler name=\""+_name+"\", flag=\""+_flag+"\", mask="+mask+"]";
		}
	}
	}