private StructureValueCollection SerializePage(ResourcePage page, FourthGenCacheFileReference[] externalFiles)
		{
			var result = new StructureValueCollection();
			result.SetInteger("salt", page.Salt);
			result.SetInteger("flags", page.Flags);
			result.SetInteger("compression codec index",
				(page.CompressionMethod != ResourcePageCompression.None) ? 0 : 0xFFFFFFFF);
			result.SetInteger("shared cache file index",
				(page.FilePath != null) ? (uint) FindExternalFile(externalFiles, page.FilePath) : 0xFFFFFFFF);
			result.SetInteger("unknown 1", (uint) page.Unknown1);
			result.SetInteger("compressed block offset", (uint) page.Offset);
			result.SetInteger("compressed block size", (uint) page.CompressedSize);
			result.SetInteger("uncompressed block size", (uint) page.UncompressedSize);
			result.SetInteger("checksum", page.Checksum);
			result.SetRaw("hash 1", page.Hash1);
			result.SetRaw("hash 2", page.Hash2);
			result.SetRaw("hash 3", page.Hash3);
			result.SetInteger("unknown 2", (uint) page.Unknown2);
			result.SetInteger("unknown 3", (uint) page.Unknown3);
			return result;
		}
		private int FindExternalFile(FourthGenCacheFileReference[] externalFiles, string path)
		{
			for (int i = 0; i < externalFiles.Length; i++)
			{
				if (externalFiles[i].Path.Equals(path, StringComparison.InvariantCultureIgnoreCase))
					return i;
			}
			throw new InvalidOperationException("Invalid shared map path \"" + path + "\"");
		}
		private ResourcePage LoadPage(StructureValueCollection values, int index, FourthGenCacheFileReference[] externalFiles)
		{
			var result = new ResourcePage();
			result.Index = index;
			result.Salt = (ushort) values.GetInteger("salt");
			result.Flags = (byte) values.GetInteger("flags");
			result.CompressionMethod = ((int) values.GetInteger("compression codec index") != -1)
				? ResourcePageCompression.Deflate
				: ResourcePageCompression.None; // FIXME: hax/laziness
			var externalFile = (int) values.GetInteger("shared cache file index");
			result.FilePath = (externalFile != -1) ? externalFiles[externalFile].Path : null;
			result.Unknown1 = (int) values.GetIntegerOrDefault("unknown 1", 0);
			result.Offset = (int) values.GetInteger("compressed block offset");
			result.CompressedSize = (int) values.GetInteger("compressed block size");
			result.UncompressedSize = (int) values.GetInteger("uncompressed block size");
			result.Checksum = values.GetInteger("checksum");
			result.Hash1 = values.GetRaw("hash 1");
			result.Hash2 = values.GetRaw("hash 2");
			result.Hash3 = values.GetRaw("hash 3");
			result.Unknown2 = (int) values.GetIntegerOrDefault("unknown 2", 0);
			result.Unknown3 = (int) values.GetIntegerOrDefault("unknown 3", 0);
			return result;
		}