private Tag decodeDoInitAction(int length)
		{
			DoInitAction t;
			t = new DoInitAction();
			int idref = r.readUI16();
			try
			{
				t.sprite = (DefineSprite) dict.getTag(idref);
				if (t.sprite.initAction != null)
				{
					handler.error("Sprite " + idref + " initaction redefined");
				}
				else
				{
					t.sprite.initAction = t;
				}
			}
			catch (System.ArgumentException e)
			{
				handler.error(e.Message);
			}
			ActionDecoder actionDecoder = new ActionDecoder(r, swd);
			actionDecoder.KeepOffsets = keepOffsets;
			t.actionList = actionDecoder.decode(length - 2);
			return t;
		}
		private Tag decodeDefineButton(int length)
		{
			int startPos = r.Offset;
			DefineButton t;
			t = new DefineButton(Flash.Swf.TagValues.stagDefineButton);
			int id = r.readUI16();
			
			System.Collections.ArrayList list = new System.Collections.ArrayList();
			ButtonRecord record;
			do 
			{
				record = decodeButtonRecord(t.code);
				if (record != null)
				{
					list.Add(record);
				}
			}
			while (record != null);
			
			t.buttonRecords = new ButtonRecord[list.Count];
			SupportClass.ICollectionSupport.ToArray(list, t.buttonRecords);
			
			// old school button actions only handle one possible transition
			int consumed = r.Offset - startPos;
			t.condActions = new ButtonCondAction[1];
			t.condActions[0].overDownToOverUp = true;
			ActionDecoder actionDecoder = new ActionDecoder(r, swd);
			actionDecoder.KeepOffsets = keepOffsets;
			t.condActions[0].actionList = actionDecoder.decode(length - consumed);
			t.trackAsMenu = false;
			
			dict.add(id, t);
			return t;
		}
		private Tag decodeDoAction(int length)
		{
			DoAction t = new DoAction();
			ActionDecoder actionDecoder = new ActionDecoder(r, swd);
			actionDecoder.KeepOffsets = keepOffsets;
			t.actionList = actionDecoder.decode(length);
			return t;
		}
		private Tag decodePlaceObject2(int length)
		{
			PlaceObject t;
			t = new PlaceObject(Flash.Swf.TagValues.stagPlaceObject2);
			r.syncBits();
			
			int pos = r.Offset;
			
			t.flags = r.readUI8();
			t.depth = r.readUI16();
			
			if (t.hasCharID())
			{
				int idref = r.readUI16();
				t.ref_Renamed = dict.getTag(idref);
			}
			if (t.hasMatrix())
			{
				t.matrix = decodeMatrix();
			}
			if (t.hasCxform())
			{
				// ed 5/22/03 the SWF 6 file format spec says this will be a CXFORM, but
				// the spec is wrong.  the player expects a CXFORMA.
				t.colorTransform = decodeCxforma();
			}
			if (t.hasRatio())
			{
				t.ratio = r.readUI16();
			}
			if (t.hasName())
			{
				t.name = r.readString();
			}
			if (t.hasClipDepth())
			{
				t.clipDepth = r.readUI16();
			}
			if (t.hasClipAction())
			{
				ActionDecoder actionDecoder = new ActionDecoder(r, swd);
				actionDecoder.KeepOffsets = keepOffsets;
				t.clipActions = actionDecoder.decodeClipActions(length - (r.Offset - pos));
			}
			return t;
		}
		private Tag decodePlaceObject23(int type, int length)
		{
			PlaceObject t = new PlaceObject(type);
			int pos = r.Offset;
			t.flags = r.readUI8();
			if (type == Flash.Swf.TagValues.stagPlaceObject3)
			{
				t.flags2 = r.readUI8();
			}
			t.depth = r.readUI16();
			if (t.hasClassName())
			{
				t.className = r.readString();
			}
			if (t.hasCharID())
			{
				int idref = r.readUI16();
				t.Ref = dict.getTag(idref);
			}
			if (t.hasMatrix())
			{
				t.matrix = decodeMatrix();
			}
			if (t.hasCxform())
			{
				t.Cxform = decodeCxforma();
			}
			if (t.hasRatio())
			{
				t.ratio = r.readUI16();
			}
			if (t.hasName())
			{
				t.name = r.readString();
			}
			if (t.hasClipDepth())
			{
				t.clipDepth = r.readUI16();
			}
			if (type == Flash.Swf.TagValues.stagPlaceObject3)
			{
				if (t.hasFilterList())
				{
					t.filters = decodeFilterList();
				}
				if (t.hasBlendMode())
				{
					t.blendMode = r.readUI8();
				}
			}
			if (t.hasClipAction())
			{
				ActionDecoder actionDecoder = new ActionDecoder(r, swd);
				actionDecoder.KeepOffsets = keepOffsets;
				t.clipActions = actionDecoder.decodeClipActions(length - (r.Offset - pos));
			}
			return t;
		}
		private ButtonCondAction decodeButtonCondAction(int length)
		{
			ButtonCondAction a = new ButtonCondAction();
			r.syncBits();
			a.keyPress = r.readUBits(7);
			a.overDownToIdle = r.readBit();
			
			a.idleToOverDown = r.readBit();
			a.outDownToIdle = r.readBit();
			a.outDownToOverDown = r.readBit();
			a.overDownToOutDown = r.readBit();
			a.overDownToOverUp = r.readBit();
			a.overUpToOverDown = r.readBit();
			a.overUpToIdle = r.readBit();
			a.idleToOverUp = r.readBit();
			
			ActionDecoder actionDecoder = new ActionDecoder(r, swd);
			actionDecoder.KeepOffsets = keepOffsets;
			a.actionList = actionDecoder.decode(length - 2);
			
			return a;
		}