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

PBJDecompiler α2

α1よりはまともになったはず。
だけど、まだどこかおかしい。
今後、もっと最適化していきたいです。

yonatanさんのコメントに感謝!
*
Get Adobe Flash player
by zahir 25 Apr 2010
/**
 * Copyright zahir ( http://wonderfl.net/user/zahir )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/sYh2
 */

/*
	α1よりはまともになったはず。
	だけど、まだどこかおかしい。
	今後、もっと最適化していきたいです。
	
	yonatanさんのコメントに感謝!
 * */
package{
	import com.bit101.components.Label;
	import com.bit101.components.PushButton;
	import com.bit101.components.Text;
	
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	
	[SWF(width="465", height="465")]
	public class PBJDecompile_test extends Sprite{
		private var btn:PushButton;
		private var fr:FileReference;
		private var txt:Text;
		private var pbj:PBJ;
		public function PBJDecompile_test(){
			var lbl:Label = new Label(this,10,0,"PBJDecompiler a2");
			lbl.scaleX = lbl.scaleY = 2;
			btn = new PushButton(this, 0,8, "load pbj file", onClick);
			btn.x = 465 - (btn.width + 10);
			draw( lbl.height * 2 );
			txt = new Text(this, 10, lbl.height * 2 + 8, "");
			txt.setSize(445, 465 - (lbl.height * 2 + 18 ) );
		}
		private function onClick(e:MouseEvent):void{
			fr = new FileReference();
			fr.addEventListener(Event.SELECT, onSelect);
			fr.browse([new FileFilter("load pbj file","*.pbj")]);
		}
		private function onSelect(e:Event):void{
			fr.removeEventListener(Event.SELECT, onSelect );
			fr.addEventListener(Event.COMPLETE, onComp);
			fr.load();
		}
		private function onComp(e:Event):void{
			fr.removeEventListener( Event.COMPLETE, onComp);
			pbj = new PBJ();
			pbj.decompile( fr.data );
			txt.text = PBJConvertString.toString( pbj );
		}
		private function draw( lineYpos:int ):void{
			var m:Matrix = new Matrix();
			m.createGradientBox(465,465, 0.01745*90 );
			var g:Graphics = graphics;
			g.beginGradientFill("linear",[0xFFFFFF, 0xCCCCCC],[1,1],[0,0xFF],m);
			g.drawRect(0,0,465,465);
			g.endFill();
			g.lineStyle(0, 0x999999);
			g.moveTo(10, lineYpos); g.lineTo( 455, lineYpos );
		}
	}
}
	import flash.utils.ByteArray;
	import flash.utils.IDataInput;
class PBJConvertString{
	static public  function toString( pbj:PBJ):String{
		var p:PBJEnum = new PBJEnum();
		var str:String = "";
		var i:int, j:int, len:int, len2:int;
		str += "Lang Version :: " + pbj.kernel.lan_version + "\n";
		str += "Kernel Name :: " + pbj.kernel.name + "\n";
		str += "namespace :: " + pbj.kernel.meta_namespace + "\n";
		str += "vendor :: " + pbj.kernel.meta_vendor + "\n";
		str += "version :: " + pbj.kernel.meta_version + "\n";
		str += "description :: " + pbj.kernel.meta_description + "\n\n";
		for(i=0,len=pbj.params.length; i<len; i++){
			var prm:PBJParameter = pbj.params[i] as PBJParameter;
			str += prm.typeString + " " + prm.name + " " + prm.index + "\n";
			if(prm.metas){
				for(j=0,len2 = prm.metas.length; j<len2; j++){
					var pm:PBJParameterMetaData = prm.metas[j] as PBJParameterMetaData;
					str += "    "
					if(pm.defaultValues)
						str += "defaultValue : " + pm.defaultValues;
					if(pm.maxValues)
						str += "maxValue : " + pm.maxValues;
					if(pm.minValues)
						str += "minValue : " + pm.minValues;
					if(pm.description)
						str += "description : " + pm.description;
					str += "\n";
				}
			}str += "\n";
		}for(i=0,len=pbj.inputs.length; i<len; i++){
			var inp:PBJInput = pbj.inputs[i] as PBJInput;
			str += inp.name + " " + inp.channels + " " + inp.index + "\n\n";
		}str += "\n;Operations num :: " + (pbj.evaluates.length) +"\n\n";
		for(i=0,len=pbj.evaluates.length;i<len;i++){
			var op:Operation = pbj.evaluates[i] as Operation;
			str += op.name + " ";
			str += " (src) :: " + p.printSrc( op.src, op.swizzle, op.size);
			str += " (dst) :: " + p.printDst(op.dst, op.mask, op.size);
			str += "\n";
		}for(i=0,len=pbj.errs.length; i<len; i++)
			str += (pbj.errs[i] as Err).msg + "\n";
		return str;
	}
}	
class PBJDecompiler{
	private var pbj:PBJ;
	private var p:PBJEnum;
	private var ba:ByteArray;
	
	private var firstins:Boolean = true;
	private var op:int;
	private var op0:uint, op1:uint, op2:uint, op3:uint;
	
	private var mask:int, swizzle:int, size:int, mtx:int;
	private var dst:uint;
	private var src:uint;
	
	private var lstParam:PBJParameter;
	private function isReg( value:int ):Boolean{
		return (value&0x8000) ? true:false;
	}
	private function bitCount( value:uint ):int{
		value = (value & 0x55555555) + (value >> 1 & 0x55555555);
		value = (value & 0x33333333) + (value >> 2 & 0x33333333);
		value = (value & 0x0f0f0f0f) + (value >> 4 & 0x0f0f0f0f);
		value = (value & 0x00ff00ff) + (value >> 8 & 0x00ff00ff);
		return (value & 0x0000ffff) + (value >>16 & 0x0000ffff);
	}
	private function readString():String{
		var pos:uint = ba.position, len:int = 0, str:String = "";
		while( ba.readUnsignedByte() ) len++;
		ba.position = pos;
		str = ba.readUTFBytes(len);
		ba.position++;
		return str;
	}
	private function readOperation():Boolean{
		ba.position--;
		if(ba.bytesAvailable < 8){
			 err(op,ba.position,"readOperation err");
			 return false;
		}
		op0 = ba.readUnsignedInt();
		op1 = ba.readUnsignedInt();
		op = (op0 >> 24) & 0xFF;
		dst = (op0 >> 8) & 0xFFFF;
		mask = (op0>>4) & 0xF;
		mtx = (op0 >> 2) & 0x3;
		size = (op0 & 3) + 1;
		src = (op1>>16) & 0xFFFF;
		swizzle = (op1>>8) & 0xFF;
		dst = ((dst >> 8) & 0xFF) | ((dst <<8) & 0xFF00);
		src = ((src >> 8) & 0xFF) | ((src <<8) & 0xFF00);
		if(op <= p.Select){
			if(mtx == 0){
				if( op == p.LoadConstant){
					// Here is what should I do? 何すればいいのこれ?
				}else if( op == p.Length){
					if(bitCount(mask) != p.SampleSizeScalar){
						err(op, ba.position-8, p.namesLo[op & 0x7F] + " sizeof( dst ) != 1");
						return false;
					}
				}else if( op == p.SampleNearest || op == p.SampleBilinear){
					if(size != p.SampleSizeVector2 ){
						err(op, ba.position-8, p.namesLo[op & 0x7F] + " sizeof( src ) != 2");
						return false;
					}
				}else if( op == p.Select){
					if(size != 1){
						err(op, ba.position-8, p.namesLo[op & 0x7F] + " sizeof( src ) != 1");
						return false;
					}
				}else
					if(bitCount(mask) != size){
						err(op, ba.position-8, p.namesLo[op & 0x7F] + " sizeof( dst ) != sizeof( src )");
						return false;
					}
			}else
				if(isReg(src) || isReg(dst)){
					err(op,ba.position - 8, p.namesLo[op&0x7F] + " operation not allowed on types");
					return false;
				}
		}
		return true;
	}
	private function setOperation():Operation{
		var o:Operation = new Operation();
		o.op = op;
		o.mtx = mtx;
		o.name = p.namesLo[op&0x7F];
		o.mtxName = p.namesMatrix[mtx];
		o.dst = dst;
		o.src  = src;
		o.size = size;
		o.mask = mask;
		o.swizzle = swizzle;
		pbj.evaluates.push( o );
		return o;
	}
	private function readArithmetic():void{
		if(!readOperation()) return;
		if(mtx){
			if(mask != 0) err(op,ba.position-8, p.namesLo[op&0x7F] + " (write mask : " + mask + ") write mask not allowed");
			switch(op){
				case p.Copy: case p.Add: case p.Subtract: case p.Multiply:
				case p.Reciprocal: case p.MatrixMatrixMultiply:
					setOperation();
					break;
				default: err(op,ba.position-8, p.namesLo[op&0x7F]+" opraton now allowed on matrices");
			}
		}else{
			var dstInt:Boolean = false, srcInt:Boolean = false;
			switch(op){
				case p.Add: case p.Subtract: case p.Multiply: case p.Divide:
					if( isReg(dst) ) dstInt = srcInt = true;
				break;
			}if( op == p.Copy){
				if( isReg( dst ) != isReg( src )){
					err(op,ba.position-8, p.namesLo[op&0x7F] + " source and destination register type mismatch");
					return
				}
			}else{
				if( isReg( dst ) != dstInt){
					err(op,ba.position-8, p.namesLo[op&0x7F] + " invalid destination register type")
					return;
				}if( isReg( src ) != srcInt){
					err(op,ba.position-8, p.namesLo[op&0x7F] + " invalid source register type");
					return;
				}
			}setOperation();
		}
	}
	private function readBoolTo():void{
		if(!readOperation()) return;
		if( !isReg(src) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " invalid source register type");
			return;
		}if( !isReg( dst ) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " invalid destination register type");
			return;
		}setOperation();
	}
	private function readMtxMulti():void{
		if(!readOperation()) return;
		if(bitCount(mask) != (mtx+1)){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " sizeof( dst ) != sizeof( src )");
			return;
		}setOperation();
	}
	private function readNormalize():void{
		if(!readOperation()) return;
		if( isReg(src) || isReg(dst) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on integer type");
			return;
		}
		if( size == p.SampleSizeScalar ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " trying to normalize a scalar");
			return;
		}else setOperation();
	}
	private function readDistLen():void{
		if(!readOperation()) return;
		if(mtx){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on matrices");
			return;
		}if( isReg(src) || isReg(dst) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on integer type");
			return;
		}if( size == p.SampleSizeScalar ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " trying to normalize a scalar");
			return;
		}else setOperation();
	}
	private function readDotProduct():void{
		if(!readOperation()) return;
		if(mtx){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on matrices");
			return;
		}if( isReg(src) || isReg(dst) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on integer type");
			return;
		}setOperation();
	}
	private function readCrossProduct():void{
		if(!readOperation()) return;
		if(mtx){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on matrices");
			return;
		}if( isReg(src) || isReg(dst) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on integer type");
			return;
		}if(size != 3){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " vector type not supported");
			return;
		}setOperation();
	}
	private function readEqual():void{
		if(!readOperation()) return;
		if(mtx){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " : " + p.namesMatrix[mtx] + " : " + dst + " : " + src);
			return;
		}else setOperation();
	}
	private function readEqual2():void{
		if(!readOperation()) return;
		if(mtx){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on matrices");
			return;
		}if( isReg(src) != isReg(dst) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " register type mismatch");
			return;
		}setOperation();
	}
	private function readLogical():void{
		if(!readOperation()) return;
		if(mtx){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on matrices");
			return;
		}if( isReg(src) || isReg(dst) ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " operation now allowed on integer type");
			return;
		}if( size == p.SampleSizeScalar ){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " ( sizeof(dst) = sizeof(src) ) != 1");
			return;
		}setOperation();
	}
	private function readSampling():void{
		if(!readOperation()) return;
		if( isReg(dst)){
			err(op,ba.position-8, p.namesLo[op&0x7F] + " Can't sample into integer registers");
			return;
		}setOperation().textureId = op1 & 0xFF;
	}
	private function readLoadConstant():void{
		if(!readOperation()) return;
		/* to do
		if( isReg(dst)){
		}else{
		}*/
	}
	private function readSelect():void{
		// not suport
		if(!readOperation()) return;
	}
	private function readInput():void{
		var inp:PBJInput = new PBJInput();
		inp.index = ba.readUnsignedByte();
		inp.channels = ba.readUnsignedByte();
		inp.name = readString();
		pbj.inputs.push( inp );
	}
	private function readParamMeta():void{
		var pm:PBJParameterMetaData = new PBJParameterMetaData();
		var type:int = ba.readUnsignedByte();
		var name:String = readString();
		var meta:String;
		if(type == p.TypeString){
			meta = readString();
			pm[name] = meta;
		}else{
			var elm:int = 0, i:int = 0;
			var arr:Array = [];
			switch(type){
				case p.TypeFloat4x4 : elm += 7;
				case p.TypeFloat3x3 : elm += 5;
				case p.TypeFloat2x2 : case p.TypeFloat4 : elm++;
				case p.TypeFloat3 : elm++;
				case p.TypeFloat2 : elm++;
				case p.TypeFloat : elm++;
					for(i=0;i<elm;i++) arr[i] = ba.readFloat(); // 何故かbigEndian
					break;
				case p.TypeBool4: case p.TypeInt4 : elm++;
				case p.TypeBool3: case p.TypeInt3 : elm++;
				case p.TypeBool2: case p.TypeInt2 : elm++;
				case p.TypeBool: case p.TypeInt : elm++;
					ba.endian = "littleEndian";
					for(i=0;i<elm;i++) arr[i] = ba.readShort();
					ba.endian = "bigEndian";
					break;
			} pm[name + "s"] = arr;
		}
		if(!lstParam.metas) lstParam.metas = [];
		lstParam.metas.push( pm );
	}
	private function readParam():void{
		var qualifier:uint = ba.readByte();
		var type:int = ba.readUnsignedByte();
		if( type == p.TypeString || qualifier > 2 || qualifier < 1){
			err(op,ba.position,"err  ::  function readParam()");
		}else{
			var param:PBJParameter = lstParam = new PBJParameter();
			param.dst  = ba.readUnsignedByte() | ba.readUnsignedByte() << 8;
			param.mask = ba.readUnsignedByte();
			param.name = readString();
			param.type = type;
			param.typeString = p.typeNames[type];
			param.size= p.typeSize[type];
			var c:String = "";
			var index:int = param.dst;
			if( index >= 32768) index -= 32768;
			if(param.mask != 0xF){
				c = index + ".";
				for(var i:int = 0; i<param.size; i++) c += p.channelName[p.map[( param.mask << 2 | i)]];
			}param.index = c;
			pbj.params.push( param );
		}
	}
	
	public function parse( pbj:PBJ, data:IDataInput , asyn:Boolean ):void{
		this.pbj = pbj;
		p = new PBJEnum();
		ba = new ByteArray();
		data.readBytes( ba );
		while( ba.bytesAvailable ){
			try{ op = ba.readUnsignedByte();
			}catch(e:Error){ err(op, ba.position-1, "Could not read UnsignByte ! ");}
			switch( op ){
				case p.Nop:
					readOperation();
					trace(p.namesLo[op&0x7F]);
					break;
				case p.Add: case p.Subtract: case p.Multiply:
				case p.Divide: case p.MatrixMatrixMultiply: case p.Atan2:
				case p.Pow: case p.Mod: case p.Min: case p.Max:
				case p.Step: case p.Copy: case p.FloatToInt:
				case p.IntToFloat: case p.Reciprocal: case p.Sin:
				case p.Cos: case p.Tan: case p.ASin: case p.ACos:
				case p.ATan: case p.Exp: case p.Exp2: case p.Log:
				case p.Log2: case p.Sqrt: case p.RSqrt: case p.Abs:
				case p.Sign: case p.Floor: case p.Ceil: case p.Fract:
				case p.FloatToBool: case p.IntToBool:
					readArithmetic();
					break;
				case p.BoolToInt: case p.BoolToFloat: case p.Any: case p.All:
					readBoolTo();
					break;
				case p.VectorMatrixMultiply: case p.MatrixVectorMultiply:
					readMtxMulti();
					break;
				case p.Normalize:
					readNormalize();
					break;
				case p.Distance: case p.Length:
					readDistLen();
					break;
				case p.DotProduct:
					readDotProduct();
					break;
				case p.CrossProduct:
					readCrossProduct();
					break;
				case p.Equal: case p.NotEqual:
					readEqual();
					break;
				case p.VectorEqual: case p.VectorNotEqual:
				case p.LessThan: case p.LessThanEqual:
					readEqual2();
					break;
				case p.LogicalOr: case p.LogicalXor:
				case p.LogicalAnd: case p.LogicalNot:
					readLogical();
					break;
				case p.SampleBilinear: case p.SampleNearest:
					readSampling();
					break;
				case p.LoadConstant:
					readLoadConstant();
					break;
				case p.Select:
					readSelect();
					break;
				case p.If:
					readOperation();
					if( !isReg(src)){
						err(op,ba.position-8, p.namesLo[op&0x7F] + " source needs to be type int");
						return;
					}setOperation();
					break;
				case p.Else:
					readOperation();
					setOperation()
					break;
				case p.Endif:
					readOperation();
					setOperation();
					break;
					
				// kernel : pramerter : input : output data
				case p.TextureData:
					readInput();
					break;
				case p.ParameterMetaData:
					readParamMeta();
					break;
				case p.ParameterData:
					readParam();
					break;
				case p.KernelMetaData:
					switch(ba.readUnsignedByte()){
						case p.TypeString:
							pbj.kernel["meta_" + readString()] = readString();
							break;
						case p.TypeInt:
							readString();
							pbj.kernel.meta_version = ba.readUnsignedByte();
							ba.position++;
							break;
					}
					break;
				case p.KernelName :
					ba.endian = "littleEndian";
					pbj.kernel.name = ba.readUTFBytes( ba.readUnsignedShort() );
					ba.endian = "bigEndian";
					break;
				case p.VersionData : 
					pbj.kernel.lan_version = ba.readUnsignedByte();
					ba.position += 3;
					break;
				default : 
					err(op, ba.position - 1, "Operation number mismatch was !");
					break;
			}
		}
	}
	private function err(op:int, pos:uint, msg:String):void{
		ba.position = ba.length;
		pbj.errs.push( new Err(op,pos,msg) );
	}
	private function toInt16( v:int ):String{
		var str:String = "0" + v.toString(16).toLocaleUpperCase();
		return "0x" + str.substr( str.length - 2,2);
	}
	private function toUint16(v:uint):String{
		var str:String = "000" + v.toString(16).toLocaleUpperCase();
		return "0x" + str.substr(str.length-4,4);
	}
}
class PBJ{
	private var dec:PBJDecompiler;
	
	public var kernel:Kernel;
	public var params:Array;
	public var inputs:Array;
	public var evaluates:Array;
	public var errs:Array;
	
	private function init():void{
		kernel = new Kernel();
		params = [];
		inputs = [];
		evaluates = [];
		errs = [];
	}
	public function decompile( data:IDataInput, asyn:Boolean = false ):void{
		if(!dec) dec = new PBJDecompiler();
		init();
		dec.parse(this,data,asyn);
	}
}
class Err{
	private var _msg:String = "";
	public function get msg():String{ return _msg; }
	public function Err(op:int, pos:uint, message:String ){
		_msg = "Error !! ";
		_msg += "pos :: " + pos;
		_msg += "    opration :: " + to16(op);
		_msg += "    " + message;
		_msg += "\n";
	}
	private function to16( v:int ):String{
		var str:String = "0" + v.toString(16).toLocaleUpperCase();
		return "0x" + str.substr( str.length - 2,2);
	}
}
class Kernel{
	public var lan_version:int;
	public var name:String;
	public var meta_namespace:String;
	public var meta_vendor:String;
	public var meta_version:int;
	public var meta_description:String;
}
class PBJInput{
	public var name:String;
	public var index:int;
	public var channels:int
}
class PBJOutput{
	public var name:String;
	public var dst:int;
	public var index:int;
	public var type:int;
	public var typeString:String;
}
class PBJParameter{
	public var name:String;
	public var metas:Array;
	public var dst:int;
	public var index:String;
	public var mask:int;
	public var size:int;
	public var type:int;
	public var typeString:String;
}
class PBJParameterMetaData{
	public var defaultValues:Array;
	public var maxValues:Array;
	public var minValues:Array;
	public var description:String;
}
class Operation{
	public var name:String;
	public var op:int;
	public var mtx:int;
	public var mtxName:String;
	public var size:int;
	public var mask:int;
	public var swizzle:int;
	public var dst:int;
	public var src:int;
	public var textureId:int;
}
class PBJEnum{
		public const Nop:int				 = 0x00;
		public const Add:int				 = 0x01;
		public const Subtract:int			 = 0x02;
		public const Multiply:int			 = 0x03;
		public const Reciprocal:int			 = 0x04;
		public const Divide:int				 = 0x05;
		public const Atan2:int				 = 0x06;
		public const Pow:int				 = 0x07;
		public const Mod:int				 = 0x08;
		public const Min:int				 = 0x09;
		public const Max:int				 = 0x0A;
		public const Step:int				 = 0x0B;
		public const Sin:int				 = 0x0C;
		public const Cos:int				 = 0x0D;
		public const Tan:int				 = 0x0E;
		public const ASin:int				 = 0x0F;
		
		public const ACos:int				 = 0x10;
		public const ATan:int				 = 0x11;
		public const Exp:int				 = 0x12;
		public const Exp2:int				 = 0x13;
		public const Log:int				 = 0x14;
		public const Log2:int				 = 0x15;
		public const Sqrt:int				 = 0x16;
		public const RSqrt:int				 = 0x17;
		public const Abs:int				 = 0x18;
		public const Sign:int				 = 0x19;
		public const Floor:int				 = 0x1A;
		public const Ceil:int				 = 0x1B;
		public const Fract:int				 = 0x1C;
		public const Copy:int				 = 0x1D;
		public const FloatToInt:int			 = 0x1E;
		public const IntToFloat:int			 = 0x1F;
		
		public const MatrixMatrixMultiply:int = 0x20;
		public const VectorMatrixMultiply:int = 0x21;
		public const MatrixVectorMultiply:int = 0x22;
		public const Normalize:int			 = 0x23;
		public const Length:int				 = 0x24;
		public const Distance:int			 = 0x25;
		public const DotProduct:int			 = 0x26;
		public const CrossProduct:int		 = 0x27;
		public const Equal:int				 = 0x28;
		public const NotEqual:int			 = 0x29;
		public const LessThan:int			 = 0x2A;
		public const LessThanEqual:int		 = 0x2B;
		public const LogicalNot:int			 = 0x2C;
		public const LogicalAnd:int			 = 0x2D;
		public const LogicalOr:int			 = 0x2E;
		public const LogicalXor:int			 = 0x2F;
		
		public const SampleNearest:int		 = 0x30;
		public const SampleBilinear:int		 = 0x31;
		public const LoadConstant:int		 = 0x32;
		public const Select:int				 = 0x33;
		public const If:int					 = 0x34;
		public const Else:int				 = 0x35;
		public const Endif:int				 = 0x36;
		public const FloatToBool:int		 = 0x37;
		public const BoolToFloat:int		 = 0x38;
		public const IntToBool:int			 = 0x39;
		public const BoolToInt:int			 = 0x3A;
		public const VectorEqual:int		 = 0x3B;
		public const VectorNotEqual:int		 = 0x3C;
		public const Any:int				 = 0x3D;
		public const All:int				 = 0x3E;
		
		public const KernelMetaData:int		 = 0xA0;
		public const ParameterData:int		 = 0xA1;
		public const ParameterMetaData:int	 = 0xA2;
		public const TextureData:int		 = 0xA3;
		public const KernelName:int			 = 0xA4;
		public const VersionData:int		 = 0xA5;
		
		public const TypeFloat:int				 = 0x01;
		public const TypeFloat2:int				 = 0x02;
		public const TypeFloat3:int				 = 0x03;
		public const TypeFloat4:int				 = 0x04;
		
		public const TypeFloat2x2:int			 = 0x05;
		public const TypeFloat3x3:int			 = 0x06;
		public const TypeFloat4x4:int			 = 0x07;
		
		public const TypeInt:int				 = 0x08;
		public const TypeInt2:int				 = 0x09;
		public const TypeInt3:int				 = 0x0A;
		public const TypeInt4:int				 = 0x0B;
		public const TypeString:int			 = 0x0C;
		public const TypeBool:int			 = 0x0D;
		public const TypeBool2:int			 = 0x0E;
		public const TypeBool3:int			 = 0x0F;
		public const TypeBool4:int			 = 0x10;
		
		public const SampleSizeScalar:int	 = 0x01;
		public const SampleSizeVector2:int	 = 0x02;
		public const SampleSizeVector3:int	 = 0x03;
		public const SampleSizeVector4:int	 = 0x04;
		
		public const namesLo:Array = [
			"nop", "add",	"sub",	"mul",	"rcp", "div", "atan2","pow", "mod", 
			"min", "max","step", "sin", "cos", "tan", "asin","acos","atan", 
			"exp", "exp2", "log","log2", "sqr", "rsqr","abs", "sign", 
			"floor", "ceil", "fract", "mov", 	"ftoi", 	"itof", 	"mmmul", "vmmul",	"mvmul", 
			"norm", "len","dist","dot", 	"cross", "equ", "neq", "ltn", "lte", 
			"not", 	"and", "or", "xor", "texn", "texb", 	"set", "sel", "if",  "else", "end", 
			"ftob", "btof", "itob", "btoi", "vequ", "vneq", "any", 	"all"
		];// end namesLo
		public const namesHi:Array = [ "kernel", "parameter", "meta", "texture", "name", "version" ];// end namesHi
		public const namesMatrix:Array = [ "", "2x2", "3x3", "4x4" ];// end namesMatrix
		public const typeSize:Array = [ 0,1,2,3,4,4,9,16,1,2,3,4,0,1,2,3,4 ];// end typeSize
		public const typeNames:Array = [
			"","float","float2","float3","float4", "matrix2x2", "matrix3x3", "matrix4x4",
			"int", "int2", "int3", "int4", "bool", "bool2", "bool3", "bool4"
		];// end namesLo
		public const qualifierName:Array = [ "","in","out"];// end qualifierName
		public const channelName:Array = ["r","g","b","a"];
		public const map:Array= [
			0x00, 0x00, 0x00, 0x00,	0x03, 0x00, 0x00, 0x00,	0x02, 0x00, 0x00, 0x00,	0x02, 0x03, 0x00, 0x00,
			0x01, 0x00, 0x00, 0x00,	0x01, 0x03, 0x00, 0x00,	0x01, 0x02, 0x00, 0x00,	0x01, 0x02, 0x03, 0x00,
			0x00, 0x00, 0x00, 0x00,	0x00, 0x03, 0x00, 0x00,	0x00, 0x02, 0x00, 0x00,	0x00, 0x02, 0x03, 0x00,
			0x00, 0x01, 0x00, 0x00,	0x00, 0x01, 0x03, 0x00,	0x00, 0x01, 0x02, 0x00,	0x00, 0x01, 0x02, 0x03,
		];
		private function Swizzle( index:int, swizzle:int):int{
			return (swizzle>>(6-index*2)) & 3;
		}
		public function printMask( mask:int, type:int):String{
			if(mask == 0xF) return "";
			var str:String = ".";
			for( var i:int = 0,len:int = typeSize[type]; i<len; i++) str+=channelName[map[(mask<<2|i)]];
			return str;
		}
		public function printDst( index:int, mask:int, size:int ):String{
			if(index >= 32768) index -= 32768;
			var str:String = index.toString( 16 );
			if(mask != 0xF) {
				str+=".";
				for(var i:int=0;i<size;i++) str+=channelName[map[(mask<<2|i)]];
			}return str;
		}
		public function printSrc( index:int, swizzle:int, size:int ):String{
			if(index >= 32768) index -= 32768;
			var str:String = index.toString( 16 );
			if(swizzle != 0x1B ) {
				str += ".";
				for(var i:int=0;i<size;i++) str+=channelName[Swizzle(i,swizzle)];
			}return str;
		}
}