perfect_dark/tools/extract-segment

83 lines
1.9 KiB
Python
Executable File

#!/usr/bin/env python3
# Extracts a segment from the binary that was produced by ld
# and unzips it if necessary. Used for `make test`.
import os
import re
import sys
import zlib
def bdir():
return 'build/%s' % os.environ['ROMID']
def find_segment(segname):
fd = open(bdir() + '/pd.map', 'r')
ldmap = fd.read()
fd.close()
start = re.findall(r'0x([0-9a-f]+)\s+_' + segname + 'SegmentRomStart = ', ldmap)[0]
end = re.findall(r'0x([0-9a-f]+)\s+_' + segname + 'SegmentRomEnd = ', ldmap)[0]
start = int(start, 16)
end = int(end, 16)
return (start, end)
def inflate(buffer):
header = int.from_bytes(buffer[0:2], 'big')
assert(header == 0x1173)
return zlib.decompress(buffer[5:], wbits=-15)
def inflate_game(buffer):
binary = bytes()
i = 0
while True:
offset = int.from_bytes(buffer[i:i+4], 'big') + 2
peek = int.from_bytes(buffer[offset:offset+2], 'big')
if peek == 0:
break
part = inflate(buffer[offset:offset+0x1000])
binary += part
if len(part) != 0x1000:
break
i += 4
return binary
def inflate_lib(buffer):
return buffer[0:0x2000] + inflate(buffer[0x2000:])
def inflate_data(buffer):
return inflate(buffer)
def main():
segname = sys.argv[1]
loadname = sys.argv[1]
if segname in ['lib', 'game', 'data']:
loadname += 'zip'
(start, end) = find_segment(loadname)
fd = open(bdir() + '/pd.z64', 'rb')
fd.seek(start)
buffer = fd.read(end - start)
fd.close()
if segname == 'lib':
buffer = inflate_lib(buffer)
elif segname == 'game':
buffer = inflate_game(buffer)
elif segname == 'data':
buffer = inflate_data(buffer)
os.makedirs(bdir() + '/segments', exist_ok=True)
fd = open(bdir() + '/segments/' + segname + '.bin', 'wb')
fd.write(buffer)
fd.close()
main()