def split_as_size(arr,size):return arr[:size],arr[size:]
class IPS:
MAGIC = b'\x50\x41\x54\x43\x48'
END = b'\x45\x4f\x46'
@classmethod
def create_from_stream(cls,stream):
return cls.create_from_bytes(stream.read())
@classmethod
def create_from_bytes(cls,byte_array):
def extract_chunk(arr):
offset,arr=split_as_size(arr,3)
size,arr=split_as_size(arr,2)
data,arr=split_as_size(arr,int.from_bytes(size))
return Chunk(offset,int.from_bytes(data)),arr
def pull_all_chunks(arr):
while len(arr)>3:
chunk,arr=extract_chunk(arr)
yield chunk
return cls(list(pull_all_chunks(byte_array)))
def __init__(self,chunks):self.chunks = chunks
def apply(self,arr):
for chunk in self.chunks:
arr[chunk.position:chunk.position+chunk.size]=chunk.data
return arr
if __name__=="__main__":
from sys import argv;argv=argv[1:]
from os.path import isfile
patches,target=[],None
for filename in argv:
if not isfile(filename):continue
if filename[:filename.rfind(".")].lower()=='ips':
patches.append(filename)
else:target=filename
if target and patches:
base_data = open(target,'rb').read()#read in the data to modify.
for patch in map(IPS.create_from_stream,map(lambda fn:open(fn,'rb'),patches)):
base_data=patch.apply(base_data)
with open('patched-{}-{}'.format("-".join(map(patch_name,patches)),target),'wb') as output:
output.write(base_data)