Files
psxrecomp/docs/beetle_spu_event_hook.patch
Shokunin 055c33aaa1 docs: complete the Beetle oracle patch set; add a macOS recipe
beetle-linux.md told builders to re-land several Beetle hooks by hand
because they were never exported to docs/: the rtrace and IRQ callbacks,
the guest-cycle clock, PS_CDC::PSXRecomp_GetDecodeVolume and the CDC/DMA
IRQ peeks that beetle_libretro.cpp links against, plus the SPU event
calls and the per-instruction hook the real cyc_watch now needs. Ship
them, one patch per hook, all against the 5759277b base:

- beetle_rtrace_irq_hook.patch
- beetle_guest_cycles_hook.patch
- beetle_cdc_dma_peek_hook.patch
- beetle_spu_event_hook.patch

beetle_cdcmd_trace_hook.patch was generated from a tree that already had
the wtrace block, so applying it after the wtrace patch redefined the
wtrace globals and typedefs and needed a manual fix. It is now a diff on
top of the wtrace and SIO patches; the resulting tree is unchanged.

beetle-macos.md is the macOS recipe, verified from a fresh official
clone on Apple Silicon: `git apply` of all seven patches, the osx static
build, the psx-beetle configure on current master, OpenBIOS under the
retail file names (Beetle otherwise boots its own, different OpenBIOS),
headless runs through SDL's dummy driver, and ruler #2 as the check
before trusting a build. beetle-linux.md now uses the full patch set,
notes the current configure requirements and the headless option, and
gives psx-beetle's actual default port (4382).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:06:14 -07:00

52 lines
2.1 KiB
Diff

diff --git a/mednafen/psx/spu.cpp b/mednafen/psx/spu.cpp
index 513628ae..b89efa08 100644
--- a/mednafen/psx/spu.cpp
+++ b/mednafen/psx/spu.cpp
@@ -73,6 +73,12 @@
#include "../state_helpers.h"
+/* PSXRecomp oracle: SPU voice event sink, defined by the psx-beetle host
+ * (runtime/src/beetle_libretro.cpp). kind: 1=KEYON 2=KEYOFF 3=END_STOP
+ * 4=END_LOOP; addr = SPU RAM address in 16-bit units; env = ADSR level. */
+extern "C" void psxrecomp_beetle_spu_event(unsigned kind, unsigned voice,
+ unsigned addr, unsigned env);
+
uint32_t IntermediateBufferPos;
int16_t IntermediateBuffer[4096][2];
@@ -328,6 +334,11 @@ void PS_SPU::RunDecoder(SPU_Voice *voice)
BlockEnd |= 1 << (voice - Voices);
+ /* PSXRecomp oracle hook: loop-end flag reached (repeat / stop). */
+ psxrecomp_beetle_spu_event((voice->DecodeFlags & 0x2) ? 4 : 3,
+ (unsigned)(voice - Voices), voice->CurAddr,
+ (unsigned)(uint16)voice->ADSR.EnvLevel);
+
if(!(voice->DecodeFlags & 0x2)) // Force enveloping to 0 if not "looping". TODO: Should we reset the ADSR divider counter too?
{
if(!(Noise_Mode & (1 << (voice - Voices))))
@@ -925,6 +936,10 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
if(voice->DecodePlayDelay < 3)
{
ReleaseEnvelope(voice);
+
+ /* PSXRecomp oracle hook: KEYOFF took effect. */
+ psxrecomp_beetle_spu_event(2, voice_num, voice->CurAddr,
+ (unsigned)(uint16)voice->ADSR.EnvLevel);
}
}
}
@@ -950,6 +965,10 @@ int32 PS_SPU::UpdateFromCDC(int32 clocks)
voice->CurPhase = 0;
voice->CurAddr = voice->StartAddr & ~0x7;
voice->IgnoreSampLA = false;
+
+ /* PSXRecomp oracle hook: KEYON took effect. */
+ psxrecomp_beetle_spu_event(1, voice_num, voice->CurAddr,
+ (unsigned)(uint16)voice->ADSR.EnvLevel);
}
if(!(SPUControl & 0x8000))