mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
Merge pull request #759 from RetroPortingToolKit/fix/spu-shadow-cd-activity-gate-20261024
Gate SPU HQ CD bypass on actual CD sample activity
This commit is contained in:
@@ -28,6 +28,7 @@ static int s_enabled = -1; /* -1 = not yet resolved */
|
||||
static int s_cfg = 0; /* config/launcher gate (env overrides) */
|
||||
static ShadowVerifier s_verifier;
|
||||
static int s_cd_bypass;
|
||||
static uint64_t s_cd_consumed;
|
||||
static SpuShadowInfo s_info;
|
||||
|
||||
void spu_shadow_set_enabled(int on) {
|
||||
@@ -52,6 +53,7 @@ bool spu_shadow_enabled(void) {
|
||||
|
||||
void spu_shadow_reset(void) {
|
||||
s_cd_bypass = 0;
|
||||
s_cd_consumed = 0;
|
||||
shadow_verifier_init(&s_verifier);
|
||||
memset(&s_info, 0, sizeof(s_info));
|
||||
s_info.enabled = spu_shadow_enabled() ? 1 : 0;
|
||||
@@ -77,7 +79,16 @@ void spu_shadow_process(int16_t* canon, int frames) {
|
||||
* canonical mix immediately, and require fresh proof when CD is disabled. */
|
||||
SpuGlobalState global;
|
||||
spu_get_global_state(&global);
|
||||
if (global.ctrl & 1u) {
|
||||
/* A game may leave CD mixing enabled throughout voice-only gameplay.
|
||||
* Gate on actual queued/consumed CD samples, including the LAST block
|
||||
* draining the FIFO. push_frames - queued includes dropped frames too;
|
||||
* treating an overflow/reset as activity is a conservative extra bypass. */
|
||||
SpuDebugInfo cd;
|
||||
spu_debug_info(&cd);
|
||||
const uint64_t consumed = cd.cd_push_frames - cd.cd_frames;
|
||||
const int cd_active = cd.cd_frames != 0 || consumed != s_cd_consumed;
|
||||
s_cd_consumed = consumed;
|
||||
if ((global.ctrl & 1u) && cd_active) {
|
||||
if (!s_cd_bypass) {
|
||||
shadow_verifier_init(&s_verifier);
|
||||
s_info.proven = 0;
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
static SpuShadowFrameTapPub taps[2048];
|
||||
static uint16_t ctrl;
|
||||
static uint64_t pushed;
|
||||
static uint32_t queued;
|
||||
void spu_debug_info(SpuDebugInfo* out) { memset(out,0,sizeof(*out));out->cd_push_frames=pushed;out->cd_frames=queued; }
|
||||
void spu_get_global_state(SpuGlobalState* out) { memset(out,0,sizeof(*out));out->ctrl=ctrl; }
|
||||
const void *spu_shadow_tap_buffer(void) { return taps; }
|
||||
int spu_shadow_tap_count(void) { return 2048; }
|
||||
@@ -49,6 +52,8 @@ int main(void) {
|
||||
assert(info.enabled && info.proven);
|
||||
assert(info.last_ratio > .99f && info.last_ratio < 1.01f);
|
||||
assert(info.last_r > .99f);
|
||||
/* The CD-enable bit alone must not disable an already proven voice mix. */
|
||||
ctrl=1;feed(48,0,1);spu_shadow_get_info(&info);assert(info.proven);
|
||||
/* A proven voice-only shadow must not replace newly starting XA/CD.
|
||||
* Synthetic CD samples, no original audio/game state. */
|
||||
ctrl=1;
|
||||
@@ -57,19 +62,23 @@ int main(void) {
|
||||
memset(taps,0,sizeof(taps));
|
||||
for(unsigned i=0;i<4096;++i)canon[i]=(int16_t)(4000+(i%511));
|
||||
memcpy(reference,canon,sizeof(canon));
|
||||
pushed+=2048;queued=0; /* Last FIFO block has drained: still CD activity. */
|
||||
spu_shadow_process(canon,2048);
|
||||
assert(memcmp(canon,reference,sizeof(canon))==0);
|
||||
spu_shadow_get_info(&info);assert(!info.proven);
|
||||
}
|
||||
ctrl=0;
|
||||
feed(48,0,2); /* CD exit cannot reuse the pre-CD proof. */
|
||||
for(unsigned block=49;block<97;++block)feed(block,0,1);
|
||||
queued=2048;
|
||||
feed(48,0,2);spu_shadow_get_info(&info);assert(!info.proven);
|
||||
queued=0;pushed+=2048;feed(49,0,2); /* Last queued block drains. */
|
||||
ctrl=1;
|
||||
feed(50,0,2); /* CD exit cannot reuse the pre-CD proof. */
|
||||
for(unsigned block=51;block<99;++block)feed(block,0,1);
|
||||
spu_shadow_get_info(&info);assert(info.proven);
|
||||
for (unsigned block = 97; block < 289; ++block) feed(block, 1, 0);
|
||||
spu_shadow_get_info(&info);
|
||||
assert(!info.proven && info.pauses > 0); /* Real guard still rejects mismatch. */
|
||||
spu_shadow_set_enabled(0); spu_shadow_reset();
|
||||
feed(240, 1, 2);
|
||||
puts("SPU shadow: normalized proof, output level, immediate CD passthrough, reproof, mismatch fallback and off passed");
|
||||
puts("SPU shadow: normalized proof, output level, idle CD enable, first/queued/last CD passthrough, reproof, mismatch fallback and off passed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user