public TextureAssociation(Register reg)
		{
			this.Texture = reg;
			this.PsSamplers = new List<int>();
			this.VsSamplers = new List<int>();
			
		}
		public bool TryGetRegister(string name, out Register register)
		{
			register = new Register();
			for (int i = 0; i < registers.Length; i++)
			{
				if (registers[i].Name == name)
				{
					register = registers[i];
					return true;
				}
			}
			return false;
		}
		public RegisterSet(string header)
		{
			//extract the registers used...
			/*
			 * Example header: 
			 * 
			//
            // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
            //
            // Parameters:
            //
            //   float2 shadowCameraNearFar;
            //
            //
            // Registers:
            //
            //   Name                Reg   Size
            //   ------------------- ----- ----
            //   shadowCameraNearFar c0       1
            //
			 * 
			 */

			Dictionary<string, Register> registers = new Dictionary<string, Register>();

			Tokenizer tokenizer = new Tokenizer(header, false, true, true);
			string[] lines = header.Split('\n');
			int state = 0;

			while (tokenizer.NextToken())
			{
				switch (tokenizer.Token)
				{
					case ":":
						break;
					case "Parameters":
						state = 1;
						break;

					case "//":

						//determine if the line has content...
						if (lines[tokenizer.Line].Trim().Length > 2)
						{

							if (state == 1)
							{
								//try and extract something

								//   float2 shadowCameraNearFar;

								tokenizer.NextToken();

								string type = tokenizer.Token;
								tokenizer.NextToken();

								if (type == "Registers")
								{
									state = 2; //done, go to registers
									break;
								}

								if (type == "struct")
								{
									string structContents = "";
									string structName = "";
									try
									{
										while (tokenizer.Token != "{")
											tokenizer.NextToken();
										tokenizer.ReadBlock();
										structContents = tokenizer.Token;
										tokenizer.NextToken();
										structName = tokenizer.Token;
									}
									catch
									{
									}
									finally
									{
										throw new CompileException(string.Format("Shader compiler cannot map the custom constant structure '{0} {1}' into a compatible XNA data structure", structName, structContents.Replace(Environment.NewLine, "").Replace("//","")));
									}
								}

								string name = tokenizer.Token;

								//possible array, or ;
								tokenizer.NextToken();
								string token = tokenizer.Token;
								int array = -1;

								if (token == "[")
								{
									tokenizer.NextToken();
									array = int.Parse(tokenizer.Token);
									tokenizer.NextToken(); //eat the ]
									tokenizer.NextToken();
								}

								//should be a ;
								if (tokenizer.Token != ";")
									throw new CompileException("Expected ';' in shader header");

								Register reg = new Register();
								reg.ArraySize = array;
								reg.Name = name;
								reg.Type = type;

								registers.Add(name, reg);
							}

							if (state == 2 || state == 3 || state == 4)
							{
								//   Name                Reg   Size
								//   ------------------- ----- ----
								//   shadowCameraNearFar c0       1

								string name, register, size;

								tokenizer.NextToken();
								name = tokenizer.Token;

								tokenizer.NextToken();
								register = tokenizer.Token;

								tokenizer.NextToken();
								size = tokenizer.Token;

								bool skip = false;

								if (name == "Name" && register == "Reg" && size == "Size")
									skip = true;
								if (name.Replace("-","").Length == 0 &&
									register.Replace("-","").Length == 0 &&
									size.Replace("-","").Length == 0)
									skip = true;

								if (!skip)
								{
									Register reg;
									if (registers.TryGetValue(name, out reg))
									{
										reg.Size = int.Parse(size);
										switch (register[0])
										{
											case 'c':
												reg.Category = RegisterCategory.Float4;
												break;
											case 'i':
												reg.Category = RegisterCategory.Integer4;
												break;
											case 'b':
												reg.Category = RegisterCategory.Boolean;
												break;
											case 't':
												reg.Category = RegisterCategory.Texture;
												break;
											case 's':
												reg.Category = RegisterCategory.Sampler;
												break;
											case 'r':
												reg.Category = RegisterCategory.Temp;
												break;
											default:
												throw new CompileException(string.Format("Unexpected constant type '{0}'", register[0]));
										}
										reg.Index = int.Parse(register.Substring(1));
										reg.Rank = ExtractRank(reg.Type, reg.Category, reg.ArraySize, reg.Size);
										registers[name] = reg;
									}
								}
							}
						}
						
						break;
				}
			}

			List<Register> registerList = new List<Register>();
			foreach (Register register in registers.Values)
				registerList.Add(register);

			this.registers = registerList.ToArray();
		}
		public RegisterSet(Register[] set)
		{
			this.registers = set;
		}
		private static void MapToValue(StringBuilder sb, Register reg, int index, string source, string arrayOffset)
		{
			if (reg.Category == RegisterCategory.Boolean)
				reg.Rank = RegisterRank.Bool;

			switch (reg.Rank)
			{
				case RegisterRank.Unknown:
					throw new ArgumentException("Unknown Register Type");

				case RegisterRank.Bool:
				case RegisterRank.FloatNx1:
				case RegisterRank.IntNx1:
					{
						sb.Append(source);
						sb.Append('[');
						sb.Append(arrayOffset);
						sb.Append("+");
						sb.Append(index++);
						sb.Append(']');

						switch (reg.Type)
						{
							case "float":
							case "bool":
							case "int":
								sb.Append(".x");
								break;
							case "int2":
							case "float2":
								sb.Append(".xy");
								break;
							case "int3":
							case "float3":
								sb.Append(".xyz");
								break;
						}
					}
					break;
				default:
					{
						sb.Append("transpose(");
						int count = 0;
						switch (reg.Rank)
						{
							case RegisterRank.FloatNx2:
							case RegisterRank.IntNx2:
								sb.Append("float2x4(");
								count = 2;
								break;
							case RegisterRank.FloatNx3:
							case RegisterRank.IntNx3:
								sb.Append("float3x4(");
								count = 3;
								break;
							case RegisterRank.FloatNx4:
							case RegisterRank.IntNx4:
								sb.Append("float4x4(");
								count = 4;
								break;
							default:
								return; //shouldn't be possible.
						}
						for (int i = 0; i < count; i++)
						{
							if (i != 0) sb.Append(',');
							sb.Append(source);
							sb.Append('[');
							if (arrayOffset.Length > 0)
							{
								sb.Append("((int)(");
								sb.Append(arrayOffset);
								sb.Append("))*");
								sb.Append(count);
							}
							sb.Append("+");
							sb.Append(index++);
							sb.Append(']');
						}
						sb.Append("))");
					}
					break;
			}
		}
		private bool ExtractRegType(string name, out Register reg, out Type dataType, out bool hasSetMethod, out int stride)
		{
			dataType = null;
			hasSetMethod = true;
			stride = 1;
			reg = new Register();

			if (!this.asm.CommonRegisters.TryGetRegister(name, out reg))
				return false;
			
			if (reg.Category == RegisterCategory.Boolean)
			{
				dataType = typeof(bool);
				hasSetMethod = false;
				return true;
			}

			if (reg.Category != RegisterCategory.Float4)
				return false;

			switch (reg.Type)
			{
				case "float":
				case "float1"://?
				case "int": // integers or bools may be processed as floats by the FX compiler
				case "int1":
				case "bool":
					dataType = typeof(float);
					hasSetMethod = false;
					break;
				case "float2":
				case "int2":
					dataType = typeof(Vector2);
					break;
				case "float3":
				case "int3":
					dataType = typeof(Vector3);
					break;
				case "float4":
				case "int4":
					dataType = typeof(Vector4);
					break;

				default:
					if (reg.Rank >= RegisterRank.IntNx1)
						return false;
					dataType = typeof(Matrix);
					stride = (int)reg.Rank;
					break;
			}
			return true;
		}
		private bool ExtractRegType(string name, out Register reg, out Type dataType)
		{
			bool hasSetMethod;
			int stride;
			return ExtractRegType(name, out reg, out dataType, out hasSetMethod, out stride);
		}
		//pull a semantic bound register
		private void ExtractSemantic(IShaderDom shader, Register reg)
		{
			string semantic = reg.Semantic;

			Type dataType = null;
			switch (reg.Rank)
			{
				case RegisterRank.FloatNx1:
				{
					switch (reg.Type)
					{
						case "float":
						case "float1"://?
							dataType = typeof(Single);
							break;
						case "float2":
							dataType = typeof(Vector2);
							break;
						case "float3":
							dataType = typeof(Vector3);
							break;
						case "float4":
							dataType = typeof(Vector4);
							break;
					}
				}
				break;
				case RegisterRank.FloatNx2:
				case RegisterRank.FloatNx3:
				case RegisterRank.FloatNx4:
					dataType = typeof(Matrix);
				break;
				case RegisterRank.IntNx1:
				case RegisterRank.IntNx2:
				case RegisterRank.IntNx3:
				case RegisterRank.IntNx4:
				{
					//ints are almost always mapped to floats for semantic bound types (EG vertex count)
					//since the register category has been validated to Float4, this is the case here
					switch (reg.Type)
					{
						case "int":
						case "int1"://?
							dataType = typeof(Single);
							break;
						case "int2":
							dataType = typeof(Vector2);
							break;
						case "int3":
							dataType = typeof(Vector3);
							break;
						case "int4":
							dataType = typeof(Vector4);
							break;
					}
				}
				break;
				case RegisterRank.Bool:
				dataType = typeof(Single);
				break;
			}

			if (reg.Category == RegisterCategory.Boolean)
				dataType = typeof(bool);
			

			if (semantic.Length == 6 && semantic.Equals("global", StringComparison.InvariantCultureIgnoreCase))
			{
				//special case global value.

				if (dataType == null)
					throw new CompileException(string.Format("Error parsing semantic for '{0}'. Global values of type '{1}' are not supported.",reg.Name, reg.Type));
				
				GlobalAttribute global = new GlobalAttribute();
				global.Register = reg;
				global.Type = dataType;

				global.GlobalIdRef = new CodeFieldReferenceExpression(shader.ShaderClassEx, string.Format("gid{0}", globals.Count));

				List<CodeFieldReferenceExpression> globalRefs = new List<CodeFieldReferenceExpression>();
				List<CodeFieldReferenceExpression> arrayRefs = new List<CodeFieldReferenceExpression>();

				foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters)
				{
					Register sreg;
					RegisterSet registers = listing.Key.RegisterSet;
					CodeExpression registersRef = listing.Value;

					if (registers.TryGetRegister(reg.Name, out sreg))
					{
						if (sreg.Category != RegisterCategory.Boolean)
						{
							string refId = string.Format("gc{0}", globalRefCount);
							globalRefs.Add(new CodeFieldReferenceExpression(shader.Instance, refId));
							globalRefCount++;
						}
					}
				}

				global.ChangeRefs = globalRefs.ToArray();

				globals.Add(global);
				return;
			}

			//special case
			bool isBlendMatrices = semantic.Equals("BLENDMATRICES", StringComparison.InvariantCultureIgnoreCase);

			if (reg.ArraySize != -1 && !isBlendMatrices)
			{
				//INVALID. EXTERMINATE.
				throw new CompileException(string.Format("Shader attribute '{0}' is defined as an array and has a semantic '{1}'. Semantics other than 'BLENDMATRICES' and 'GLOBAL' are invalid for Array types.", reg.Name, reg.Semantic));
			}

			bool isTranspose = semantic.Length > 9 && semantic.EndsWith("transpose", StringComparison.InvariantCultureIgnoreCase);

			if (isTranspose)
				semantic = semantic.Substring(0, semantic.Length - 9);

			SemanticType? dataSemanticType = null;

			foreach (SemanticType semanticType in semanticTypes)
			{
				if (semanticType.Type == dataType &&
					semanticType.Mapping.Equals(semantic, StringComparison.InvariantCultureIgnoreCase))
				{
					dataSemanticType = semanticType;
					break;
				}
			}

			if (dataSemanticType == null)
			{
				//INVALID. EXTERMINATE.
				throw new CompileException(string.Format("Shader attribute '{0}' has unrecognised semantic '{1}'.", reg.Name, reg.Semantic));
			}

			//create the mapping...
			SemanticMapping mapping = new SemanticMapping();
			mapping.Register = reg;
			mapping.Type = dataSemanticType.Value;

			//figure out how often this semantic is used..
			List<CodeFieldReferenceExpression> changeRefs = new List<CodeFieldReferenceExpression>();

			foreach (KeyValuePair<AsmListing, CodeExpression> listing in listingRegisters)
			{
				Register sreg;
				RegisterSet registers = listing.Key.RegisterSet;
				CodeExpression registersRef = listing.Value;

				if (registers.TryGetRegister(reg.Name, out sreg))
				{
					string changeId = string.Format("sc{0}", semanticMappingRefCount++);
					changeRefs.Add(new CodeFieldReferenceExpression(shader.Instance, changeId));
				}
			}

			mapping.ChangeRefs = changeRefs.ToArray();

			this.semanticMapping.Add(mapping);
		}
		private void AssignRegister(Type dataType, Register targetRegister, Register sourceRegister, CodeExpression codeExpression, CodeExpression valueRef, CodeStatementCollection statements, ref bool tempValuesCreated)
		{
			int arrayLength = Math.Max(1, targetRegister.ArraySize);
			bool isArray = targetRegister.ArraySize > 0;

			CodeExpression temp = null, loopIndex = null;
			if (isArray)
			{
				if (!tempValuesCreated)
				{
					statements.Add(new CodeVariableDeclarationStatement(dataType, "val"));
					statements.Add(new CodeVariableDeclarationStatement(typeof(int), "i"));

					//copies of readindex/writeindex
					statements.Add(new CodeVariableDeclarationStatement(typeof(uint), "ri"));
					statements.Add(new CodeVariableDeclarationStatement(typeof(uint), "wi"));
					tempValuesCreated = true;
				}

				loopIndex = new CodeVariableReferenceExpression("i");
				temp = new CodeVariableReferenceExpression("val");

				statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("ri"), new CodeArgumentReferenceExpression("readIndex")));
				statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("wi"), new CodeArgumentReferenceExpression("writeIndex")));
			}
			else
				loopIndex = new CodePrimitiveExpression(0);

			bool isMatrix = dataType == typeof(Matrix);
			bool isFloat = targetRegister.Rank >= RegisterRank.FloatNx1 && targetRegister.Rank <= RegisterRank.FloatNx4;
		
			int count = 1;
			switch (targetRegister.Rank)
			{
				case RegisterRank.FloatNx2:
				case RegisterRank.IntNx2:
					count = 2;
					break;
				case RegisterRank.FloatNx3:
				case RegisterRank.IntNx3:
					count = 3;
					break;
				case RegisterRank.FloatNx4:
				case RegisterRank.IntNx4:
					count = 4;
					break;
			}

			CodeExpression countRef = new CodeArgumentReferenceExpression("count");
			CodeExpression readIndexRef = new CodeArgumentReferenceExpression("ri");
			CodeExpression writeIndexRef = new CodeArgumentReferenceExpression("wi");
			CodeExpression valueLength = new CodePropertyReferenceExpression(valueRef, "Length");

			//check the incomming array
			if (isArray)
			{
				arrayLength = targetRegister.Size / count;

				//validate the input is not null
				CodeConditionStatement check = new CodeConditionStatement(
					new CodeBinaryOperatorExpression(valueRef, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)),
					new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(ArgumentNullException),new CodePrimitiveExpression("value"))));
					
				statements.Add(check);

				//validate the array args are good.
				/*
			if (readIndex + count > value.Length ||
				writeIndex + count > 10)
				throw new System.ArgumentException("Input array is either null or too short");
*/
				CodeExpression readCompare = new CodeBinaryOperatorExpression(
					new CodeBinaryOperatorExpression(readIndexRef, CodeBinaryOperatorType.Add, countRef),
					 CodeBinaryOperatorType.GreaterThan, valueLength);
				CodeExpression writeCompare = new CodeBinaryOperatorExpression(
					new CodeBinaryOperatorExpression(writeIndexRef, CodeBinaryOperatorType.Add, countRef),
					 CodeBinaryOperatorType.GreaterThan, new CodePrimitiveExpression(sourceRegister.ArraySize));

				check = new CodeConditionStatement(
					new CodeBinaryOperatorExpression(readCompare, CodeBinaryOperatorType.BooleanOr, writeCompare),
					new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(ArgumentException),
						new CodePrimitiveExpression("Invalid range"))));

				statements.Add(check);
			}
			List<CodeStatement> innerStatements = new List<CodeStatement>();

			//genrate the code to set the registers
			{
				CodeExpression valueTarget = valueRef;

				if (targetRegister.ArraySize > 0)
				{
					innerStatements.Add(new CodeAssignStatement(temp, new CodeArrayIndexerExpression(valueRef, readIndexRef)));
					valueTarget = temp;
				}

				for (int i = 0; i < count; i++)
				{
					//register index to write:
					CodeExpression arrayIndex = new CodePrimitiveExpression(i + targetRegister.Index);

					//loop is a bit more complex: loopIndex * count + i + reg.Index
					if (isArray)
						arrayIndex = 
							new CodeBinaryOperatorExpression(
								new CodeBinaryOperatorExpression(writeIndexRef, CodeBinaryOperatorType.Multiply, new CodePrimitiveExpression(count)),
								CodeBinaryOperatorType.Add,
								arrayIndex);

					CodeExpression assignTarget = new CodeArrayIndexerExpression(codeExpression,
						arrayIndex);

					//float3x2 is rank 2, so 2 vectors are written.
					//each vector is 3 elements, so work out how many to write in XYZW per vector:
					
					//default the elements to zero.
					CodeExpression x = new CodePrimitiveExpression(0.0f), y = x, z = x, w = x;

					//get the first number of the '3x2' part of the type, eg from float3x2
					int number = 1;

					//find the first number in the type name, if there is one.
					foreach (char c in targetRegister.Type)
					{
						if (char.IsNumber(c))
						{
							number = int.Parse(c.ToString());
							break;
						}
					}
					
					//simple assignment:
					if (number == 4 && count == 1) // float4 or int4
					{
						//directly assign the value
						innerStatements.Add(new CodeAssignStatement(assignTarget, valueTarget));
						continue;
					}
					
					//set the x,y,z,w coords
					if (number >= 4)
						w = new CodeFieldReferenceExpression(valueTarget, isMatrix ? "M4" + (i+1) : "W");
					if (number >= 3)
						z = new CodeFieldReferenceExpression(valueTarget, isMatrix ? "M3" + (i+1) : "Z");
					if (number >= 2)
						y = new CodeFieldReferenceExpression(valueTarget, isMatrix ? "M2" + (i+1) : "Y");
					if (!isMatrix && number == 1)
						x = valueTarget; // float doesn't have a member
					else
						x = new CodeFieldReferenceExpression(valueTarget, isMatrix ? "M1" + (i+1) : "X");

					//and assign..
					innerStatements.Add(new CodeAssignStatement(assignTarget, new CodeObjectCreateExpression(typeof(Vector4), x,y,z,w)));
				}
			}

			if (isArray)
			{
				//generate the assignment loop
					
			//	for (int i = 0; i < count; i++)
			//	{
			//	...
			//	readIndex++, writeIndex++
			//	}

				//add readIndex & writeIndex increment
				innerStatements.Add(new CodeAssignStatement(readIndexRef, new CodeBinaryOperatorExpression(readIndexRef, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))));
				innerStatements.Add(new CodeAssignStatement(writeIndexRef, new CodeBinaryOperatorExpression(writeIndexRef, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))));

				CodeIterationStatement loop = new CodeIterationStatement(
					new CodeAssignStatement(loopIndex,new CodePrimitiveExpression(0)),
					new CodeBinaryOperatorExpression(
						new CodeBinaryOperatorExpression(loopIndex, CodeBinaryOperatorType.LessThan, countRef),
						CodeBinaryOperatorType.BooleanAnd,
						new CodeBinaryOperatorExpression(writeIndexRef, CodeBinaryOperatorType.LessThan, new CodePrimitiveExpression(arrayLength))),
					new CodeAssignStatement(loopIndex,new CodeBinaryOperatorExpression(loopIndex, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))),
					innerStatements.ToArray());
				statements.Add(loop);
			}
			else
				statements.AddRange(innerStatements.ToArray());
		}
		private ShaderExtensionGenerator(SourceShader shader, Platform platform, string techniquePostfix)
		{
			this.techniquePostfix = techniquePostfix;

			//this method temporary modifies the HlslStructure stored in the source shader, so take a backup first.
			structureBackup = new Dictionary<HlslStructure, HlslStructure.ShaderStatement[]>();
			BackupStructure(shader.HlslShader);
			

			RegisterSet registers     = shader.GetDecompiledEffect(platform).EffectRegisters;

			List<string> addRegisters = new List<string>();

			methodList = shader.GetAllMethods(platform, true).ToArray();

			foreach (var method in methodList)
			{
				if (methodNames.ContainsKey(method.Name))
					continue;

				bool open = false;
				bool args = false;

				//work out if this method takes args
				foreach (var element in method.HlslShader.Elements)
				{
					if (open)
					{
						if (element == ")")
							open = false;
						else
							args = true;
					}
					if (element == "(")
						open = true;
				}

				methodNames.Add(method.Name,args);
			}

			//collect up the declared world matrices
			foreach (var reg in registers)
			{
				if (reg.Semantic != null && reg.Semantic.StartsWith("WORLD", StringComparison.InvariantCultureIgnoreCase))
				{
					string replaceWith = reg.Semantic.Substring(5);

					//see if the replacement exists.
					if (replaceWith.Length > 0)
					{
						bool createReg = true;

						foreach (var r2 in registers)
						{
							if (r2.Semantic != null && r2.Semantic.Equals(replaceWith, StringComparison.InvariantCultureIgnoreCase))
							{
								createReg = false;
								matrixRemap.Add(reg.Name, new MatrixMapping() { Name = reg.Name, RemapTo = r2.Name + worldMatrixName, BaseName  = r2.Name});
							}
						}

						if (createReg)
						{
							addRegisters.Add(replaceWith);
							matrixRemap.Add(reg.Name, new MatrixMapping() { Name = reg.Name, RemapTo = ToInternalMatrixName(reg.Name), BaseName = ToInternalMatrixName(replaceWith) }); 
						}
					}
					else
						worldMatrix = reg;
				}
			}

			header.AppendLine();
			header.AppendFormat("float4 {0}[216] : BLENDMATRICES; ", blendMatricesName);
			header.AppendLine();
			//add the new registers
			foreach (var reg in addRegisters)
			{
				header.AppendFormat("float4x4 {0} : {1}; ", ToInternalMatrixName(reg), reg);
				header.AppendLine();
			}

			methodSignatureAppend = "";
			methodCallAppend      = "";

			foreach (var remap in matrixRemap.Values)
			{
				methodSignatureAppend += string.Format("float4x4 {0}, ", remap.RemapTo);
				methodCallAppend      += string.Format("{0}, ", remap.RemapTo);
			}
			methodSignatureAppend += "float4x4 " + worldMatrixName;
			methodCallAppend      += worldMatrixName;

			if (worldMatrix.Name != null)
			{
				matrixRemap.Add(worldMatrix.Name, new MatrixMapping() { Name = worldMatrix.Name, RemapTo = worldMatrixName });
			}


			BuildTechniqueMethod(shader, ShaderExtension.Blending);
			BuildTechniqueMethod(shader, ShaderExtension.Instancing);

			foreach (var tech in shader.GetAllTechniques())
			{
				if (tech.Platform == platform || tech.Platform == Platform.Both)
				{
					AsmTechnique asmTechnique = shader.GetAsmTechnique(tech.Name, platform);
					rootVsMethodName = tech.VertexShaderMethodName;
					GenerateTechnique(shader, tech, asmTechnique, platform);
				}
			}

			header.Append(builtShader);
			header.Append(footer);

			result = header.ToString();
		}
		public DecompiledEffect(SourceShader source, Platform platform)
		{
			this.techniqueDefaults = new Dictionary<string, TechniqueExtraData>();

			var handler = new EffectHandler();
			handler.source = source.ShaderSource;
			handler.filename = source.FileName;
			handler.buildForXbox = platform == Platform.Xbox;

			//create the native DX decompiler wrapper
			var decompiler = new Native.ShaderDecompiler(ASCIIEncoding.ASCII.GetBytes(source.ShaderSource), source.FileName, platform == Platform.Xbox, handler);
			
			Effect effect = handler.Effect;

			if (decompiler.Errors != null && decompiler.GetShaderCode() == null)
				Common.ThrowError(decompiler.Errors);
			
			//now pull the good stuff out.

			List<Register> registers = new List<Register>();
			List<Register> textures = new List<Register>();

			for (int i = 0; i < effect.Parameters.Count; i++)
			{
				Register register = new Register();

				if (effect.Parameters[i].ParameterType == EffectParameterType.Single ||
					effect.Parameters[i].ParameterType == EffectParameterType.Int32 ||
					effect.Parameters[i].ParameterType == EffectParameterType.Bool)
				{
					register.Name = effect.Parameters[i].Name;
					register.Semantic = effect.Parameters[i].Semantic;
					register.ArraySize = effect.Parameters[i].Elements.Count;
					register.Size = effect.Parameters[i].RowCount * Math.Max(1, register.ArraySize);
					registers.Add(register);
				}

				if (effect.Parameters[i].ParameterType >= EffectParameterType.Texture &&
					effect.Parameters[i].ParameterType <= EffectParameterType.TextureCube)
				{
					EffectParameterType type = effect.Parameters[i].ParameterType;
					if (type == EffectParameterType.Texture1D)
						type = EffectParameterType.Texture2D;

					register.Name = effect.Parameters[i].Name;
					register.Semantic = effect.Parameters[i].Semantic;
					register.Type = type.ToString();
					textures.Add(register);
					register.Category = RegisterCategory.Texture;
					registers.Add(register);
				}

			}

			//iterate the samplers (XNA 4 removed the ability to query samplers!)
			var samplers = decompiler.GetSamplers();
			for (int i = 0; i < samplers.Length; i++)
			{
				var sampler = new Register();
				sampler.Name = samplers[i].Name;
				sampler.Semantic = samplers[i].Semantic;
				sampler.Type = samplers[i].Type;
				sampler.Category = RegisterCategory.Sampler;
				registers.Add(sampler);
			}
			
			//null any empty semantics
			for (int i = 0; i < registers.Count; i++)
			{
				Register reg = registers[i];
				if (reg.Semantic != null && reg.Semantic.Length == 0)
					reg.Semantic = null;
				registers[i] = reg;
			}

			this.effectRegisters = new RegisterSet(registers.ToArray());
			this.decompiledAsm = decompiler.DisassembledCode;

			ExtractEffectDefaults(effect, textures, source, platform);

			effect.Dispose();
			effect = null;
		}
		private void SetupCommonRegisters()
		{
			Dictionary<string, Register> common = new Dictionary<string, Register>();

			AsmListing[] listings = new AsmListing[] { vsListing, psListing, vsBlendOverride, vsInstancingOverride };

			foreach (AsmListing listing in listings)
			{
				if (listing == null)
					continue;

				for (int i = 0; i < listing.RegisterSet.RegisterCount; i++)
				{
					Register reg = listing.RegisterSet.GetRegister(i);

					if (!common.ContainsKey(reg.Name))
						common.Add(reg.Name, reg);
				}
			}

			Register[] registers = new Register[common.Count];
			int count = 0;

			foreach (Register reg in common.Values)
			{
				registers[count++] = reg;
			}

			this.registers = new RegisterSet(registers);
		}
Beispiel #13
0
        public RegisterSet(string header)
        {
            //extract the registers used...

            /*
             * Example header:
             *
             * //
             * // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
             * //
             * // Parameters:
             * //
             * //   float2 shadowCameraNearFar;
             * //
             * //
             * // Registers:
             * //
             * //   Name                Reg   Size
             * //   ------------------- ----- ----
             * //   shadowCameraNearFar c0       1
             * //
             *
             */

            Dictionary <string, Register> registers = new Dictionary <string, Register>();

            Tokenizer tokenizer = new Tokenizer(header, false, true, true);

            string[] lines = header.Split('\n');
            int      state = 0;

            while (tokenizer.NextToken())
            {
                switch (tokenizer.Token)
                {
                case ":":
                    break;

                case "Parameters":
                    state = 1;
                    break;

                case "//":

                    //determine if the line has content...
                    if (lines[tokenizer.Line].Trim().Length > 2)
                    {
                        if (state == 1)
                        {
                            //try and extract something

                            //   float2 shadowCameraNearFar;

                            tokenizer.NextToken();

                            string type = tokenizer.Token;
                            tokenizer.NextToken();

                            if (type == "Registers")
                            {
                                state = 2;                                         //done, go to registers
                                break;
                            }

                            if (type == "struct")
                            {
                                string structContents = "";
                                string structName     = "";
                                try
                                {
                                    while (tokenizer.Token != "{")
                                    {
                                        tokenizer.NextToken();
                                    }
                                    tokenizer.ReadBlock();
                                    structContents = tokenizer.Token;
                                    tokenizer.NextToken();
                                    structName = tokenizer.Token;
                                }
                                catch
                                {
                                }
                                finally
                                {
                                    throw new CompileException(string.Format("Shader compiler cannot map the custom constant structure '{0} {1}' into a compatible XNA data structure", structName, structContents.Replace(Environment.NewLine, "").Replace("//", "")));
                                }
                            }

                            string name = tokenizer.Token;

                            //possible array, or ;
                            tokenizer.NextToken();
                            string token = tokenizer.Token;
                            int    array = -1;

                            if (token == "[")
                            {
                                tokenizer.NextToken();
                                array = int.Parse(tokenizer.Token);
                                tokenizer.NextToken();                                         //eat the ]
                                tokenizer.NextToken();
                            }

                            //should be a ;
                            if (tokenizer.Token != ";")
                            {
                                throw new CompileException("Expected ';' in shader header");
                            }

                            Register reg = new Register();
                            reg.ArraySize = array;
                            reg.Name      = name;
                            reg.Type      = type;

                            registers.Add(name, reg);
                        }

                        if (state == 2 || state == 3 || state == 4)
                        {
                            //   Name                Reg   Size
                            //   ------------------- ----- ----
                            //   shadowCameraNearFar c0       1

                            string name, register, size;

                            tokenizer.NextToken();
                            name = tokenizer.Token;

                            tokenizer.NextToken();
                            register = tokenizer.Token;

                            tokenizer.NextToken();
                            size = tokenizer.Token;

                            bool skip = false;

                            if (name == "Name" && register == "Reg" && size == "Size")
                            {
                                skip = true;
                            }
                            if (name.Replace("-", "").Length == 0 &&
                                register.Replace("-", "").Length == 0 &&
                                size.Replace("-", "").Length == 0)
                            {
                                skip = true;
                            }

                            if (!skip)
                            {
                                Register reg;
                                if (registers.TryGetValue(name, out reg))
                                {
                                    reg.Size = int.Parse(size);
                                    switch (register[0])
                                    {
                                    case 'c':
                                        reg.Category = RegisterCategory.Float4;
                                        break;

                                    case 'i':
                                        reg.Category = RegisterCategory.Integer4;
                                        break;

                                    case 'b':
                                        reg.Category = RegisterCategory.Boolean;
                                        break;

                                    case 't':
                                        reg.Category = RegisterCategory.Texture;
                                        break;

                                    case 's':
                                        reg.Category = RegisterCategory.Sampler;
                                        break;

                                    case 'r':
                                        reg.Category = RegisterCategory.Temp;
                                        break;

                                    default:
                                        throw new CompileException(string.Format("Unexpected constant type '{0}'", register[0]));
                                    }
                                    reg.Index       = int.Parse(register.Substring(1));
                                    reg.Rank        = ExtractRank(reg.Type, reg.Category, reg.ArraySize, reg.Size);
                                    registers[name] = reg;
                                }
                            }
                        }
                    }

                    break;
                }
            }

            List <Register> registerList = new List <Register>();

            foreach (Register register in registers.Values)
            {
                registerList.Add(register);
            }

            this.registers = registerList.ToArray();
        }
		private static void ThrowSamplerNoTextureException(Register reg)
		{
			throw new CompileException(string.Format("Texture Sampler '{0} {1}' is not bound to a named Texture{2}The sampler must define a default sampler state, in the example format:{2}{2}texture{3} {1}Texture;{2}{0} {1} = sampler_state{2}{4}{2}\tTexture = ({1}Texture);{2}{5}; ", reg.Type, reg.Name, Environment.NewLine, reg.Type.Length >= 7 ? reg.Type.Substring(7) : "", "{", "}"));
		}