/// <summary> /// Writes out the constants to the SWF file. This will also re-set the tables in the /// code object, so be sure you don't have anything in there that you need. /// </summary> /// <param name="writer">Where to write the constants to.</param> /// <param name="code">The code object with the tables in it, that we'll /// overwrite.</param> private void WriteConstantPool(ABCDataTypeWriter writer, AbcCode code) { /* Integer constants */ int[] ints = this.intMarshal.ToArray(); writer.WriteU30Packed((uint)(ints.Length == 1 ? 0 : ints.Length)); for (int i = 1; i < ints.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const int #" + i + ": " + ints[i]); #endif writer.WriteSI32(ints[i]); } code.IntConsts = ints; /* Unsigned integer constants */ uint[] uints = this.uintMarshal.ToArray(); writer.WriteU30Packed((uint)(uints.Length == 1 ? 0 : uints.Length)); for (int i = 1; i < uints.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const uint #" + i + ": " + uints[i]); #endif writer.WriteUI32(uints[i]); } code.UIntConsts = uints; /* Double constants */ ulong[] doubles = this.doubleMarshal.ToArray(); writer.WriteU30Packed((uint)(doubles.Length == 1 ? 0 : doubles.Length)); for (int i = 1; i < doubles.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const double (bits) #" + i + ": " + doubles[i]); #endif /* We hack this here instead of having a U64 type, because it's a hack around not * treating double properly. There's no such thing as U64 in SWF. */ ulong d = doubles[i]; uint low = (uint)(d & 0x00000000FFFFFFFF); d >>= 32; uint high = (uint)(d & 0x00000000FFFFFFFF); writer.WriteUI32(high); writer.WriteUI32(low); } code.DoubleConsts = doubles; /* String constants */ string[] strings = this.stringMarshal.ToArray(); writer.WriteU30Packed((uint)(strings.Length == 1 ? 0 : strings.Length)); for (int i = 1; i < strings.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const string #" + i + ": \"" + strings[i] + "\""); #endif writer.WriteString(strings[i]); } code.StringConsts = strings; /* Namespace constants */ Namespace[] namespaces = this.nsMarshal.ToArray(); writer.WriteU30Packed((uint)(namespaces.Length == 1 ? 0 : namespaces.Length)); for (int i = 1; i < namespaces.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const ns #" + i + ": " + namespaces[i]); #endif Namespace ns = namespaces[i]; writer.WriteUI8((uint)ns.Kind); writer.WriteU30Packed((uint)this.stringMarshal.GetExistingIDFor(ns.Name)); } code.SetNamespaces(namespaces); /* Namespace set constants */ NamespaceSet[] namespaceSets = this.nsSetMarshal.ToArray(); writer.WriteU30Packed((uint)(namespaceSets.Length == 1 ? 0 : namespaceSets.Length)); for (int i = 1; i < namespaceSets.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const ns set #" + i + ": " + namespaceSets[i]); #endif NamespaceSet nss = namespaceSets[i]; writer.WriteU30Packed((uint)nss.Count); foreach (Namespace ns in nss) { writer.WriteU30Packed((uint)this.nsMarshal.GetExistingIDFor(ns)); } } code.SetNamespaceSets(namespaceSets); /* Multiname constants */ Multiname[] multinames = this.multinameMarshal.ToArray(); writer.WriteU30Packed((uint)(multinames.Length == 1 ? 0 : multinames.Length)); for (int i = 1; i < multinames.Length; i++) /* Omit value at [0] */ { #if DEBUG this.writeLog.AppendLine("Const mn set #" + i + ": " + multinames[i]); #endif Multiname mn = multinames[i]; writer.WriteUI8((uint)mn.Kind); switch (mn.Kind) { case Multiname.MultinameKind.QName: case Multiname.MultinameKind.QNameA: uint nsIdx = (uint)this.nsMarshal.GetExistingIDFor(mn.NS); uint nameIdx = (uint)this.stringMarshal.GetExistingIDFor(mn.Name); writer.WriteU30Packed(nsIdx); writer.WriteU30Packed(nameIdx); break; case Multiname.MultinameKind.RTQName: case Multiname.MultinameKind.RTQNameA: writer.WriteU30Packed((uint)this.stringMarshal.GetExistingIDFor(mn.Name)); break; case Multiname.MultinameKind.RTQNameL: case Multiname.MultinameKind.RTQNameLA: /* No data */ break; case Multiname.MultinameKind.Multiname: case Multiname.MultinameKind.MultinameA: writer.WriteU30Packed((uint)this.stringMarshal.GetExistingIDFor(mn.Name)); writer.WriteU30Packed((uint)this.nsSetMarshal.GetExistingIDFor(mn.Set)); break; case Multiname.MultinameKind.MultinameL: case Multiname.MultinameKind.MultinameLA: writer.WriteU30Packed((uint)this.nsSetMarshal.GetExistingIDFor(mn.Set)); break; default: break; } } code.SetMultinames(multinames); }