mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
f75159c8d6
Root cause: BIOS music engine reads voice register 6 (byte offset 0x0C, CURVOL / ADSR_LEVEL) to find a free voice; recomp returned the never- written spu_regs value (always 0), so the engine saw every voice as silent and over-recycled voices 0-3 instead of fanning across all 24. After fix, recomp KEYON-per-voice counts match Beetle exactly (e.g. v0 2/2, v18 2/2, v22 1/1). Also: - Full ADSR envelope (Attack/Decay/Sustain/Release) ported from Beetle's CalcVCDelta/RunEnvelope. KEYOFF now triggers Release-phase decay rather than immediate silencing. - End-without-loop triggers Release (matches RunDecoder), not active=0. - ENDX latch at 0x1F801D9C/9E now reports actual block-end-reached state instead of active-mask. - SPU event ring (KEYON/KEYOFF/END_STOP/END_LOOP) on both backends with frame-stamped per-voice payload; 1 M entries each (32 MB) for chime + game-scene headroom. Beetle-side env>0 filter so silent-loop noise doesn't bury the audible-voice timeline (matches recomp behavior where deactivated voices don't fire further events). - spu_voices / spu_events / spu_events_reset debug-server commands on both ports. send_fmt buffer kept single-shot to avoid extra newlines. - tools/_spu_ring_diff.py: frame-aligned event-ring diff with per-voice count summary; chunk-count cap removed (was aborting reads at 98 KB). - tools/_spu_capture.py, _spu_probe.py, _probe_one.py: targeted probes used during diagnosis. Local-only beetle-psx change (gitignored): same env>0 filter at mednafen/psx/spu.cpp around line 345/352. Rebuild beetle-psx static lib if reapplying. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
26 lines
833 B
Python
26 lines
833 B
Python
import socket, json, sys
|
|
port = int(sys.argv[1]); cnt = int(sys.argv[2])
|
|
s = socket.create_connection(('127.0.0.1', port), timeout=5)
|
|
s.settimeout(5)
|
|
s.sendall(('{"cmd":"spu_events","id":1,"count":%d}\n' % cnt).encode())
|
|
buf = b''
|
|
while True:
|
|
try:
|
|
c = s.recv(1 << 20)
|
|
except socket.timeout:
|
|
print('TIMEOUT after', len(buf), 'bytes')
|
|
break
|
|
if not c:
|
|
print('EOF after', len(buf), 'bytes')
|
|
break
|
|
buf += c
|
|
if b'\n' in buf:
|
|
print('GOT NEWLINE at', buf.index(b'\n'), '/', len(buf), 'bytes total')
|
|
break
|
|
line = buf.split(b'\n', 1)[0]
|
|
try:
|
|
j = json.loads(line)
|
|
print('parse OK, total=', j['total'], 'count=', j['count'], 'events_len=', len(j['events']))
|
|
except Exception as e:
|
|
print('parse FAIL:', e, ' line len:', len(line), ' tail-300:', line[-300:])
|