#!/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()