mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
6e6a0b3ed8
Closes the four gaps named in issue #103 and lands the separable, verified parts of PR #102. See docs/internal/SPU_FIDELITY_103.md for the per-piece disposition and the oracle-verification queue. SPU DSP (issue #103), clean-room from hardware documentation: - Reverb: the documented 22050 Hz engine — vLIN/vRIN input, same-side and crossed different-side IIR reflections, 4-tap comb early echo, both all-pass filters, vLOUT/vROUT output, and the work-area address advance. Gated on SPUCNT bit 7 for WRITES only; reads, IRQ checks, address advance and output always run, as on hardware. Addressing is confined to [mBASE, 0x80000). Per-voice sends from EON, CD send from SPUCNT bits 0+2. - Noise: 16-bit LFSR with the documented parity feedback, clocked at the SPUCNT bits 8-13 rate; NON voices substitute it for their ADPCM sample. - Volume sweeps: all 24 voice L/R plus main L/R. Bit 15 selects sweep vs direct; sweep is a live envelope on the same rate machinery as ADSR, and a guest read of a sweeping register returns the live level. - Capture buffers: CD L/R and voice 1/3 output written to SPU RAM, so a game that parks the IRQ address there still gets its interrupt. - SPU IRQ (I_STAT bit 9): checked at every SPU RAM access class — FIFO, DMA both directions, ADPCM block fetch, capture writes, reverb work-area accesses — gated on SPUCNT bit 6, mirrored in SPUSTAT bit 6, acked by clearing SPUCNT bit 6. The CD-only fast path in spu_render was removed rather than extended: the SPU now has per-frame work that must run in every path, and an FMV (XA audio with zero active voices) is exactly the CD-with-reverb case. This is a clean-room implementation from the psx-spx/nocash register map and documented algorithm. Beetle's source was deliberately not consulted: it is GPL-2.0-or-later and this project is PolyForm Noncommercial. PR #16 was parked for exactly that reason and PR #13's reverb was separately wrong (it gated on bit 15 of dAPF1, an address offset, instead of SPUCNT bit 7). The one place this knowingly deviates from hardware is the 22.05 -> 44.1 kHz reconstruction filter, which the documentation does not specify; it is isolated in a single function and flagged for oracle comparison. CAUSE.IP2 (from PR #102): IP2 is combinational on R3000A — it mirrors the interrupt line and falls the instant the guest acks I_STAT or masks the source. It was being OR'd in at delivery and never cleared, in TWO places (the compiled path and psx_interpreter.c, the latter missed by PR #102), leaving a phantom pending interrupt that can spin a kernel dispatcher looping on CAUSE.IP & SR.IM. psx_irq_refresh_cause_ip2() is now the sole writer of bit 10, refreshed at raise, I_STAT ack, I_MASK write, HLE context restore and power-on. Verified against the Beetle oracle's irq.cpp/cpu.cpp rather than asserted, and covered by test_cause_ip2_combinational. Mid-dispatch audio pump (from PR #102), with a fix: routed through a gate that mirrors sdl_audio_update's mute/sink decision. Pumping unconditionally from the VBlank edge, as submitted, would have pushed real audio during every turbo-load hard mute and defeated the freeze-in-place mute model. SPU RAM DMA readback (from PR #102): DMA4 in the SPU->RAM direction wrote literal zeros; SPU RAM is readable memory and titles carry state through it across an Exec boundary. Also fixes an unrelated build race found on the way: tools/embed_spirv.py wrote its intermediate SPIR-V to <source>.spv, so the two runtime targets that embed the same shaders raced on one path and one deleted the file the other was reading. Co-Authored-By: Alexandros Mandravillis <Alexbeav@live.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Internal dev-logs & design notes
These are the working design documents and burn-down logs the project was built from. They are historical/working notes, not contributor onboarding docs — they capture decisions, phased plans, and deep subsystem investigations in the order they happened, and some sections are superseded by later ones.
If you're new here, start with the top-level README.md,
then docs/ARCHITECTURE.md,
docs/EXECUTION_MODEL.md,
docs/BUILDING.md, and
CONTRIBUTING.md. Come here when you need the why
behind a specific subsystem.
Plans & roadmap
PLAN.md— the original phased build plan (P1–P6).FAITHFUL_TIMING_PLAN.md— the authoritative cycle-accuracy north-star plan and status log.FIRST_MILESTONE.md— the first-boot milestone gate.STUBS_TO_FIX.md— hardware-stub burn-down (pre-game gate).
Cycle accuracy & timing
PRECISE_IRQ_SLICE.md— exact-instruction IRQ delivery.CYCLE_MODEL_BEETLE.md— the Beetle-derived cycle model.ACCURACY_BURNDOWN.md— full accuracy burn-down across all axes (semantics, cycle, IRQ, MMIO, peripherals, determinism).COSIM_ORACLE.md— the first-divergence co-sim oracle.
BIOS / scheduler
HLE_SCHEDULER_CARVEOUT_PLAN.md— the cooperative-thread scheduler HLE carve-out.WEDGE_load4_shell_rootcause.md— a specific boot-shell wedge root-cause writeup.
Renderer / widescreen
GL_RENDERER_HANDOFF.md— OpenGL renderer design.NATIVE_WIDE_PLAN.md— native-wide 16:9 (GTE FOV) plan.BACKDROP_PRELOAD.md— widescreen backdrop preload.
Overlay cache internals
SLJIT_PERSIST_CACHE.md— persisted overlay-shard cache design.