48 lines
1.3 KiB
Python
Executable File
48 lines
1.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import sys, os
|
|
import shutil
|
|
|
|
def perform_ips_patch(patch_file, base_file, output_file, ips32):
|
|
# IPS32 features not yet implemented
|
|
magic = patch_file.read(5)
|
|
if magic != b"PATCH":
|
|
print("Invalid ips patch!")
|
|
return -1
|
|
|
|
shutil.copyfile(base_file, output_file)
|
|
output_file = open(output_file, "rb+")
|
|
|
|
offset = patch_file.read(3)
|
|
while offset != b"EOF":
|
|
offset = (int(offset[0]) << 16) + (int(offset[1]) << 8) + int(offset[2])
|
|
length = patch_file.read(2)
|
|
length = (int(length[0]) << 8) + int(length[1])
|
|
output_file.seek(offset)
|
|
if length != 0: # Normal mode
|
|
data = patch_file.read(length)
|
|
output_file.write(data)
|
|
else: # RLE Mode
|
|
count = patch_file.read(2)
|
|
count = (int(count[0]) << 8) + int(count[1])
|
|
byte = patch_file.read(1)
|
|
output_file.write(byte * count)
|
|
offset = patch_file.read(3)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
if len(sys.argv) < 4:
|
|
print("Usage: ips.py <patch file> <base file> <output file> [ips32] \
|
|
\nSpecifying anything for ips32 will result in it patching as if the patch format is ips32 instead of ips")
|
|
exit()
|
|
|
|
if not (os.path.exists(sys.argv[1]) and os.path.exists(sys.argv[2])):
|
|
print("Warning: one of the input files does not exist")
|
|
exit()
|
|
|
|
patch_file = open(sys.argv[1], "rb")
|
|
|
|
perform_ips_patch(patch_file, sys.argv[2], sys.argv[3], len(sys.argv) > 4)
|