PBJDecompiler α2
α1よりはまともになったはず。
だけど、まだどこかおかしい。
今後、もっと最適化していきたいです。
yonatanさんのコメントに感謝!
*
/**
* 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;
}
}