import struct
data = open(r'C:\git\bt411\content\BTL4.RES', 'rb').read()
labOnly, maxID = struct.unpack_from('<ii', data, 4)
offs = struct.unpack_from('<%dI' % maxID, data, 12)

# resource record: [id][type][name 32][size?][dataOffset?] -- find layout empirically
# checkres used: rid, rt at +0, +4; name at +8..+40.  Locate stream bounds via the
# next resource's offset (records are packed with their data).
recs = []
for o in offs:
    if o == 0:
        continue
    rid, rt = struct.unpack_from('<ii', data, o)
    nm = data[o + 8:o + 40].split(b'\0')[0].decode('ascii', 'replace')
    recs.append((o, rid, rt, nm))
recs.sort()

def stream_of(target_id):
    for i, (o, rid, rt, nm) in enumerate(recs):
        if rid == target_id:
            end = recs[i + 1][0] if i + 1 < len(recs) else len(data)
            # header: id,type,name32 then likely [size][...]; data runs to `end`
            return data[o:end], nm
    return None, None

def root_y(rid, label):
    blob, nm = stream_of(rid)
    if blob is None:
        print(label, rid, 'NOT FOUND'); return
    # find the ANI payload: after the 40-byte record header there may be extra
    # header ints; the payload starts [A][B][x] with plausible counts.
    for hdr in range(40, 72, 4):
        A, B = struct.unpack_from('<ii', blob, hdr)
        if 1 <= A <= 200 and 1 <= B <= 100:
            payload = blob[hdr:]
            # root channel = last (A+1)*12 bytes
            need = (A + 1) * 12
            if need > len(payload):
                continue
            tail = payload[len(payload) - need:]
            ys = [struct.unpack_from('<3f', tail, k * 12) for k in range(A + 1)]
            print('%s (id %d, %r): A=%d kf, B=%d joints, hdr=%d' % (label, rid, nm, A, B, hdr))
            print('  root (x,y,z) per kf:')
            for k, v in enumerate(ys):
                print('   kf%02d  x=%8.3f  y=%8.3f  z=%8.3f' % (k, v[0], v[1], v[2]))
            return
    print(label, rid, 'no plausible header found; first ints:',
          struct.unpack_from('<8i', blob, 40))

root_y(908, 'blhbmp (knockdown)')
print()
root_y(898, 'blhwwl (walk-left, baseline)')
