Initial commit: soothe2 RE workspace + roadmap
- Инфраструктура: RTTI-дампы (rtti_dsp/full.json), декомпиляции DSP-классов (decomp_*.txt), Ghidra-скрипты (Dump*.java, ImportRtti*.java, Diag.java), depthcurve/curve_fits LUT. - Поведенческая модель sim_v5.py + sim.py (RMSE ~0.3dB), утилиты (measure, tt_sweep, patchparam, sweep, harness_*, verify_sim). - summary.md + roadmap.md (контракт из manual M1-M12, топология пайплайна из OCR, фазы A-C). - pipeline_ocr.txt: OCR диаграммы Appendix A (mid/side ручка, trim/mix/bypass порядок).
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
import os, glob, sys, time, subprocess
|
||||
|
||||
REAPER = "/usr/bin/reaper"
|
||||
RPP = "/home/m/soothe-bt/render_long.rpp"
|
||||
OUTDIR = "/home/m/re-tools/regions_render"
|
||||
|
||||
os.makedirs(OUTDIR, exist_ok=True)
|
||||
|
||||
def all_procs():
|
||||
out = {}
|
||||
for p in glob.glob('/proc/[0-9]*'):
|
||||
try:
|
||||
pid = int(os.path.basename(p))
|
||||
cmd = open(p + '/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
|
||||
st = open(p + '/stat','rb').read().decode('utf8','replace')
|
||||
ppid = int(st.split(')')[-1].split()[3]) # rough: parse later
|
||||
state = st.split(')')[-1].split()[0]
|
||||
out[pid] = (ppid, state, cmd.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return out
|
||||
|
||||
def wait_full(pid, base=0x180000000, extent=0x7000000, tmo=40):
|
||||
start = time.time()
|
||||
while time.time() - start < tmo:
|
||||
try:
|
||||
maps = open(f'/proc/{pid}/maps').read()
|
||||
except Exception:
|
||||
return False
|
||||
seen = 0
|
||||
for line in maps.splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) < 6: continue
|
||||
lo, hi = (int(x,16) for x in parts[0].split('-'))
|
||||
if 'r' in parts[1] and base <= lo < base+extent:
|
||||
seen += 1
|
||||
if lo <= 0x184000000 < hi:
|
||||
return True
|
||||
if seen < 8:
|
||||
time.sleep(1)
|
||||
continue
|
||||
# big enough set of readable regions present; dump what exists
|
||||
return True
|
||||
|
||||
def dump_module(pid, base=0x180000000, extent=0x7000000):
|
||||
maps_path = f'/proc/{pid}/maps'
|
||||
maps = open(maps_path).read()
|
||||
readable = []
|
||||
for line in maps.splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) < 6: continue
|
||||
addr, perms, off, dev, ino, *rest = parts
|
||||
lo, hi = (int(x,16) for x in addr.split('-'))
|
||||
if 'r' in perms and (base <= lo < base+extent):
|
||||
readable.append((lo, hi, perms))
|
||||
print(f' pid {pid}: {len(readable)} readable regions in [{base:#x},{base+extent:#x})')
|
||||
if not readable:
|
||||
print(' LISTING MAPS around base:')
|
||||
for line in maps.splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) < 6: continue
|
||||
addr, perms, *rest = parts
|
||||
lo = int(addr.split('-')[0],16)
|
||||
if base-0x100000 <= lo <= base+0x1000000:
|
||||
print(' ', line)
|
||||
mem = os.open(f'/proc/{pid}/mem', os.O_RDONLY)
|
||||
total = 0
|
||||
for lo, hi, perms in readable:
|
||||
size = hi - lo
|
||||
try:
|
||||
data = os.pread(mem, size, lo)
|
||||
total += len(data)
|
||||
fn = os.path.join(OUTDIR, f'pid{pid}_{lo:08x}_{hi:08x}_{perms.replace("-","")}.bin')
|
||||
with open(fn,'wb') as f: f.write(data)
|
||||
print(f' dumped {lo:#x}-{hi:#x} {len(data):#x} bytes {perms}')
|
||||
except Exception as e:
|
||||
print(f' {lo:#x}-{hi:#x} {perms} FAIL {e}')
|
||||
os.close(mem)
|
||||
print(f' pid {pid} total {total} bytes')
|
||||
|
||||
print("spawning reaper...")
|
||||
proc = subprocess.Popen(
|
||||
[REAPER, "-nosplash", "-renderproject", RPP],
|
||||
stdout=open('/tmp/harness.log','w'), stderr=subprocess.STDOUT,
|
||||
env={**os.environ})
|
||||
print("reaper pid", proc.pid)
|
||||
|
||||
deadline = time.time() + 120
|
||||
dumped = False
|
||||
while time.time() < deadline and proc.poll() is None:
|
||||
time.sleep(1)
|
||||
procs = all_procs()
|
||||
for pid,(ppid,state,cmd) in list(procs.items()):
|
||||
if state != 'S': continue
|
||||
if 'yabridge' in cmd or 'wine' in cmd:
|
||||
with open(f'/proc/{pid}/maps') as f:
|
||||
if 'soothe2' in f.read():
|
||||
ok = wait_full(pid)
|
||||
print(f' wait_full(pid {pid}): {ok}')
|
||||
if not ok:
|
||||
continue
|
||||
dump_module(pid)
|
||||
dumped = True
|
||||
time.sleep(2)
|
||||
if dumped:
|
||||
break
|
||||
if not dumped:
|
||||
print("no live soothe2 process observed")
|
||||
print("killing reaper")
|
||||
proc.terminate()
|
||||
time.sleep(1)
|
||||
if proc.poll() is None:
|
||||
proc.kill()
|
||||
Reference in New Issue
Block a user