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)