import struct
data = open(r'C:\git\bt411\content\BTL4OPT.EXE', 'rb').read()
e = struct.unpack_from('<I', data, 0x3C)[0]; coff = e+4
num = struct.unpack_from('<H', data, coff+2)[0]; osz = struct.unpack_from('<H', data, coff+16)[0]
opt = coff+20; base = struct.unpack_from('<I', data, opt+28)[0]; sect = opt+osz
secs = []
for i in range(num):
    o = sect+i*40
    vs, va, rs, rp = struct.unpack_from('<IIII', data, o+8)
    secs.append((va, vs, rp, rs))

def off2va(off):
    for va, vs, rp, rs in secs:
        if rp <= off < rp+rs:
            return base+va+(off-rp)
    return None

targets = {0x49ed0c: 'FUN_0049ed0c (glue: table->zone) == the handler',
           0x49de14: 'FUN_0049de14 (cell->zone roll)'}
cva, cvs, crp, crs = secs[0]
for i in range(crp, crp+crs-5):
    if data[i] == 0xE8:
        rel = struct.unpack_from('<i', data, i+1)[0]
        site = off2va(i)
        tgt = site+5+rel
        if tgt in targets:
            print('call site VA %08x -> %s' % (site, targets[tgt]))
