Example #1
0
        public Patcher(string patch_id)
        {
            // build the location of the patch definition resource
            // open the resource for reading
            Stream xml_stream = null;

            xml_stream = GetType().Assembly.GetManifestResourceStream(String.Format("FilePatcher.PatchDefinitions.{0}.xml", patch_id));
            if (xml_stream == null)
            {
                throw new Exception(String.Format("Matching patch definition for {0} was not found. Inform the developers of the problem.", patch_id));
            }

            // deserialize the definition xml
            XmlSerializer serializer = new XmlSerializer(typeof(FilePatch));

            m_file_patch = serializer.Deserialize(xml_stream) as FilePatch;

            if (m_file_patch == null)
            {
                throw new Exception(String.Format("Failed to deserialize a file patch xml {0}. Inform the developers of the problem.", patch_id));
            }

            // create the message list
            ErrorMessages = new List <string>();
        }
Example #2
0
		private bool WriteData(uint address, FilePatch.Data data, Stream output)
		{
			uint peaddress = 0;
			if(!ParseHex(m_file_patch.PEAddressMaskString, out peaddress))
			{
				ErrorMessages.Add(String.Format("Failed to parse PE address mask string ({0}). Inform the developers of this.", data.ID));
				return false;
			}

			// calculate the byte address and move to it
			long write_address = address - peaddress;

			if (write_address >= output.Length)
			{
				ErrorMessages.Add(String.Format("Failed to write patch data ({0}) as the pointer is beyond the end of the file. Inform the developers of this.", data.ID));
				return false;
			}

			output.Seek(write_address, SeekOrigin.Begin);
			
			int write_length = data.Length;
			switch (data.Type)
			{
				case FilePatch.ValueType.String:
					{
						// default write length to te length of the string if zero
						if(write_length == 0)
							write_length = data.Value.Length;

						if ((write_address + write_length) >= output.Length)
						{
							ErrorMessages.Add(String.Format("Failed to write patch data ({0}) as the data would write beyond the end of the file. Inform the developers of this.", data.ID));
							return false;
						}

						// write the strings bytes as ASCII
						byte[] bytes = Encoding.ASCII.GetBytes(data.Value);
						output.Write(bytes, 0, write_length);

						// if necessary, write a null character to terminate the string
						if (data.WriteNull)
							output.WriteByte(0);
					}
					break;
				case FilePatch.ValueType.UInteger32:
					{
						if ((write_address + 4) >= output.Length)
						{
							ErrorMessages.Add(String.Format("Failed to write patch data ({0}) as the data would write beyond the end of the file. Inform the developers of this.", data.ID));
							return false;
						}

						// try and parse the hex string
						uint parsed_value;
						if (!ParseHex(data.Value, out parsed_value))
						{
							ErrorMessages.Add(String.Format("Failed to parse a uint32 ({0}). Inform the developers of this.", data.ID));
							return false;
						}

						// swap the uint's endianness if required
						if (data.SwapEndian)
						{
							uint endian_swapped = 0;
							endian_swapped |= (uint)((parsed_value & 0xff000000) >> 24);
							endian_swapped |= (uint)((parsed_value & 0x00ff0000) >> 8);
							endian_swapped |= (uint)((parsed_value & 0x0000ff00) << 8);
							endian_swapped |= (uint)((parsed_value & 0x000000ff) << 24);

							parsed_value = endian_swapped;
						}

						// write the value to the stream
						output.Write(BitConverter.GetBytes(parsed_value), 0, 4);
					}
					break;
				case FilePatch.ValueType.UInteger16:
					{
						if ((write_address + 2) >= output.Length)
						{
							ErrorMessages.Add(String.Format("Failed to write patch data ({0}) as the data would write beyond the end of the file. Inform the developers of this.", data.ID));
							return false;
						}

						// try and parse the hex string
						ushort parsed_value;
						if (!ParseHex(data.Value, out parsed_value))
						{
							ErrorMessages.Add(String.Format("Failed to parse a uint16 ({0}). Inform the developers of this.", data.ID));
							return false;
						}

						// swap the uint's endianness if required
						if (data.SwapEndian)
						{
							ushort endian_swapped = 0;
							endian_swapped |= (ushort)((parsed_value & 0xff00) >> 8);
							endian_swapped |= (ushort)((parsed_value & 0x00ff) << 8);

							parsed_value = endian_swapped;
						}

						// write the value to the stream
						output.Write(BitConverter.GetBytes(parsed_value), 0, 2);
					}
					break;
				case FilePatch.ValueType.Byte:
					{
						if ((write_address + 1) >= output.Length)
						{
							ErrorMessages.Add(String.Format("Failed to write patch data ({0}) as the data would write beyond the end of the file. Inform the developers of this.", data.ID));
							return false;
						}

						// try and parse the hex string
						byte parsed_value;
						if (!ParseHex(data.Value, out parsed_value))
						{
							ErrorMessages.Add(String.Format("Failed to parse a byte ({0}). Inform the developers of this.", data.ID));
							return false;
						}

						// write the value to the stream
						output.WriteByte(parsed_value);
					}
					break;
				case FilePatch.ValueType.Bytes:
					{
						// check the strings length is a multiple of two
						if (data.Value.Length % 2 != 0)
						{
							ErrorMessages.Add(String.Format("The length of a hex byte string ({0}) in the file patcher is odd. Inform the developers.", data.ID));
							return false;
						}

						// create the byte array
						using (MemoryStream byte_stream = new MemoryStream())
						{
							// convert every two characters into a byte
							for (int i = 0; i < data.Value.Length; i += 2)
							{
								byte parsed_byte = 0;
								if(!ParseHex(data.Value.Substring(i, 2), out parsed_byte))
								{
									ErrorMessages.Add(String.Format("Failed to parse a byte array ({0}). Inform the developers of this.", data.ID));
									return false;
								}

								byte_stream.WriteByte(parsed_byte);
							}

							// default the write length to the array length if zero
							if (write_length == 0)
								write_length = (int)byte_stream.Length;

							if ((write_address + write_length) >= output.Length)
							{
								ErrorMessages.Add(String.Format("Failed to write patch data ({0}) as the data would write beyond the end of the file. Inform the developers of this.", data.ID));
								return false;
							}

							// write the byte array to the stream
							output.Write(byte_stream.GetBuffer(), 0, write_length);
						}
					}
					break;
			}

			return true;
		}
Example #3
0
		private bool ApplyPatch(FilePatch.Patch patch, Stream file)
		{
			// apply each patch
			foreach (var address in patch.Addresses)
			{
				// find a matching data block
				FilePatch.Data data = patch.Data.Find(
					delegate(FilePatch.Data value)
					{
						if (address.Value.Equals(value.ID))
							return true;
						return false;
					}
				);

				// error if a data block was not found
				if (data == null)
				{
					ErrorMessages.Add(String.Format("A patch address references an invalid data id ({0}). Inform the developers of this", address.Value));
					return false;
				}

				// parse the address
				uint pointer = 0;
				if (!ParseHex(address.PTRString, out pointer))
				{
					ErrorMessages.Add(String.Format("Failed to parse an addresses pointer string ({0}). Inform the developers of this", address.Value));
					return false;
				}

				// write the data to the current address
				if (!WriteData(pointer, data, file))
					return false;
			}
			return true;
		}
Example #4
0
		public Patcher(string patch_id)
		{
			// build the location of the patch definition resource
			// open the resource for reading
			Stream xml_stream = null;
			xml_stream = GetType().Assembly.GetManifestResourceStream(String.Format("FilePatcher.PatchDefinitions.{0}.xml", patch_id));
			if (xml_stream == null)
				throw new Exception(String.Format("Matching patch definition for {0} was not found. Inform the developers of the problem.", patch_id));
			
			// deserialize the definition xml
			XmlSerializer serializer = new XmlSerializer(typeof(FilePatch));
			m_file_patch = serializer.Deserialize(xml_stream) as FilePatch;

			if (m_file_patch == null)
				throw new Exception(String.Format("Failed to deserialize a file patch xml {0}. Inform the developers of the problem.", patch_id));

			// create the message list
			ErrorMessages = new List<string>();
		}