#!/usr/bin/env python3 """rtcapture.py — runtime-захват soothe2 из yabridge-host во время offline-рендера. Запускает reaper -renderproject , находит yabridge-host.exe.so с soothe2_x64.vst3, вычисляет runtime-базу модуля (по MZ/PE) и непрерывно сэмплирует целевую RAM плагина (RVA = VA - 0x180000000). Печатает последние стабильные значения по окончании рендера. Цели (RVA от базы модуля): 0x540658 окно/FIR (размер окна из plan) [искомое 0.540658] 0x540678 per-bin уровень-трекеры 0x5407c8 аккумулятор маски (C) 0x540698 freq-axis значение 0x540534 N/2 (FFT size) 0x5408b0 узлы кривой 0x188 (20 doubles) 0x540888 0x540880 ctor-константы 0x540530..0x5405a0 план-таблицы FFT """ import os, sys, glob, time, struct, subprocess RPP = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/render_long.rpp' BASE = 0x180000000 TARGETS = { 'window_0x540658': (0x540658, 0x1000), 'levels_0x540678': (0x540678, 0x400), 'acc_0x5407c8': (0x5407c8, 0x40), 'freqaxis_0x540698': (0x540698, 0x20), 'n2_0x540534': (0x540534, 0x20), 'curve_0x5408b0': (0x5408b0, 0x200), 'ctor_0x540870': (0x540870, 0x60), 'plan_0x540530': (0x540530, 0x80), } def find_base(pid): maps = open(f'/proc/{pid}/maps').read() mem = os.open(f'/proc/{pid}/mem', os.O_RDONLY) seen = set() for line in maps.splitlines(): p = line.split() lo = int(p[0].split('-')[0], 16) if lo in seen: continue seen.add(lo) try: hdr = os.pread(mem, 0x1000, lo) except Exception: continue if hdr[:2] != b'MZ': continue try: x = struct.unpack(' 1e-9] print(f'{name:20s} nonzero={len(nz)} first20={nz[:20]}') elif name == 'acc_0x5407c8': print(f'{name:20s} ints={[hex(v) for v in vals[:8]]}') elif name == 'curve_0x5408b0': dl = struct.unpack('<%dd' % (len(d) // 8), d[:len(d) // 8 * 8]) print(f'{name:20s} doubles={[round(v, 6) for v in dl[:20]]}') elif name == 'levels_0x540678': fl = struct.unpack('<%df' % (len(d) // 4), d[:len(d) // 4 * 4]) print(f'{name:20s} floats={[round(v, 5) for v in fl[:40]]}') elif name in ('ctor_0x540870',): fl = struct.unpack('<%df' % (len(d) // 4), d[:len(d) // 4 * 4]) print(f'{name:20s} floats={[round(v, 5) for v in fl[:16]]}') elif name in ('plan_0x540530',): print(f'{name:20s} ints={[hex(v) for v in vals[:24]]}') else: print(f'{name:20s} ints={[hex(v) for v in vals[:8]]}') print('done') if __name__ == '__main__': main()