From b118ffadea31a5258a11d28f462263d594b69ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 12 Jan 2023 11:30:42 +0100 Subject: [PATCH 1/3] Add workaround for hung music notes in Rockman Dash 2 Fixes #11442. Or at least should, I haven't tested this, just followed the discussion in the issue. According to this issue, this is a game bug that happens on real hardware too, due to a lousy job porting the game to the PSP, most likely, which has different ADSR (note envelope) behavior. --- Core/Compatibility.cpp | 1 + Core/Compatibility.h | 1 + Core/HW/SasAudio.cpp | 7 ++++++- assets/compat.ini | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 60790ddbfc40..0a79f798100b 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -124,6 +124,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "OldAdrenoPixelDepthRoundingGL", &flags_.OldAdrenoPixelDepthRoundingGL); CheckSetting(iniFile, gameID, "ForceCircleButtonConfirm", &flags_.ForceCircleButtonConfirm); CheckSetting(iniFile, gameID, "DisallowFramebufferAtOffset", &flags_.DisallowFramebufferAtOffset); + CheckSetting(iniFile, gameID, "RockmanDash2SoundFix", &flags_.RockmanDash2SoundFix); } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index d5c03f42f075..99b16ce525e0 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -95,6 +95,7 @@ struct CompatFlags { bool OldAdrenoPixelDepthRoundingGL; bool ForceCircleButtonConfirm; bool DisallowFramebufferAtOffset; + bool RockmanDash2SoundFix; }; struct VRCompat { diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 4d85d0fd7ca5..08393bf48590 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -25,6 +25,7 @@ #include "Core/Config.h" #include "Core/Reporting.h" #include "Core/Util/AudioFormat.h" +#include "Core/Core.h" #include "SasAudio.h" // #define AUDIO_TO_FILE @@ -894,7 +895,11 @@ inline void ADSREnvelope::Step() { SetState(STATE_SUSTAIN); break; case STATE_SUSTAIN: - WalkCurve(sustainType, sustainRate); + if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) { + WalkCurve(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE, sustainRate); + } else { + WalkCurve(sustainType, sustainRate); + } if (height_ <= 0) { height_ = 0; SetState(STATE_RELEASE); diff --git a/assets/compat.ini b/assets/compat.ini index 1bff998155d9..68e46c2fb578 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -1424,3 +1424,9 @@ UCES01264 = true UCJS10107 = true NPJG00073 = true UCAS40262 = true + +[RockmanDash2SoundFix] +# Rockman Dash 2, see #11442 +ULJM05037 = true +ULJM05216 = true +NPJH50181 = true \ No newline at end of file From 92585403c42dca933df94c07f87fa103a7a5e736 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 14 Jan 2023 16:55:40 -0800 Subject: [PATCH 2/3] Sas: Make ADSR fields private. --- Core/HLE/sceSas.cpp | 12 +++--------- Core/HW/SasAudio.cpp | 22 ++++++++++++++++++++++ Core/HW/SasAudio.h | 25 +++++++++++++++---------- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index a0450efa5a4f..c7dc08805e67 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -536,7 +536,7 @@ static u32 sceSasSetSL(u32 core, int voiceNum, int level) { DEBUG_LOG(SCESAS, "sceSasSetSL(%08x, %i, %08x)", core, voiceNum, level); __SasDrain(); SasVoice &v = sas->voices[voiceNum]; - v.envelope.sustainLevel = level; + v.envelope.SetSustainLevel(level); return 0; } @@ -556,10 +556,7 @@ static u32 sceSasSetADSR(u32 core, int voiceNum, int flag, int a, int d, int s, __SasDrain(); SasVoice &v = sas->voices[voiceNum]; - if ((flag & 0x1) != 0) v.envelope.attackRate = a; - if ((flag & 0x2) != 0) v.envelope.decayRate = d; - if ((flag & 0x4) != 0) v.envelope.sustainRate = s; - if ((flag & 0x8) != 0) v.envelope.releaseRate = r; + v.envelope.SetRate(flag, a, d, s, r); return 0; } @@ -602,10 +599,7 @@ static u32 sceSasSetADSRMode(u32 core, int voiceNum, int flag, int a, int d, int DEBUG_LOG(SCESAS, "sceSasSetADSRMode(%08x, %i, %i, %08x, %08x, %08x, %08x)", core, voiceNum, flag, a, d, s, r); __SasDrain(); SasVoice &v = sas->voices[voiceNum]; - if ((flag & 0x1) != 0) v.envelope.attackType = a; - if ((flag & 0x2) != 0) v.envelope.decayType = d; - if ((flag & 0x4) != 0) v.envelope.sustainType = s; - if ((flag & 0x8) != 0) v.envelope.releaseType = r; + v.envelope.SetEnvelope(flag, a, d, s, r); return 0; } diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 08393bf48590..e76fcfd8fe79 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -318,6 +318,28 @@ static int getSustainLevel(int bitfield1) { return ((bitfield1 & 0x000F) + 1) << 26; } +void ADSREnvelope::SetEnvelope(int flag, int a, int d, int s, int r) { + if ((flag & 0x1) != 0) + attackType = a; + if ((flag & 0x2) != 0) + decayType = d; + if ((flag & 0x4) != 0) + sustainType = s; + if ((flag & 0x8) != 0) + releaseType = r; +} + +void ADSREnvelope::SetRate(int flag, int a, int d, int s, int r) { + if ((flag & 0x1) != 0) + attackRate = a; + if ((flag & 0x2) != 0) + decayRate = d; + if ((flag & 0x4) != 0) + sustainRate = s; + if ((flag & 0x8) != 0) + releaseRate = r; +} + void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) { attackRate = getAttackRate(ADSREnv1); attackType = getAttackType(ADSREnv1); diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 4e9670c1364c..bae8b738d9f4 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -151,6 +151,11 @@ class ADSREnvelope { public: ADSREnvelope(); void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2); + void SetEnvelope(int flag, int a, int d, int s, int r); + void SetRate(int flag, int a, int d, int s, int r); + void SetSustainLevel(int sl) { + sustainLevel = sl; + } void WalkCurve(int type, int rate); @@ -170,16 +175,6 @@ class ADSREnvelope { return state_ == STATE_OFF; } - int attackRate; - int decayRate; - int sustainRate; - int releaseRate; - int attackType; - int decayType; - int sustainType; - int sustainLevel; - int releaseType; - void DoState(PointerWrap &p); private: @@ -197,6 +192,16 @@ class ADSREnvelope { }; void SetState(ADSRState state); + int attackRate; + int decayRate; + int sustainRate; + int releaseRate; + int attackType; + int decayType; + int sustainType; + int sustainLevel; + int releaseType; + ADSRState state_; s64 height_; // s64 to avoid having to care about overflow when calculating. TODO: this should be fine as s32 }; From 9909e0d66812bf301d44ddb7047d1a100803a67c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 14 Jan 2023 16:57:49 -0800 Subject: [PATCH 3/3] Sas: Adjust Rockman 2 sustain on init only. --- Core/HW/SasAudio.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index e76fcfd8fe79..a8a2f6d56d12 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -327,6 +327,10 @@ void ADSREnvelope::SetEnvelope(int flag, int a, int d, int s, int r) { sustainType = s; if ((flag & 0x8) != 0) releaseType = r; + + if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) { + sustainType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; + } } void ADSREnvelope::SetRate(int flag, int a, int d, int s, int r) { @@ -351,6 +355,10 @@ void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) { releaseType = getReleaseType(ADSREnv2); sustainLevel = getSustainLevel(ADSREnv1); + if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) { + sustainType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; + } + if (attackRate < 0 || decayRate < 0 || sustainRate < 0 || releaseRate < 0) { ERROR_LOG_REPORT(SASMIX, "Simple ADSR resulted in invalid rates: %04x, %04x", ADSREnv1, ADSREnv2); } @@ -917,11 +925,7 @@ inline void ADSREnvelope::Step() { SetState(STATE_SUSTAIN); break; case STATE_SUSTAIN: - if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) { - WalkCurve(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE, sustainRate); - } else { - WalkCurve(sustainType, sustainRate); - } + WalkCurve(sustainType, sustainRate); if (height_ <= 0) { height_ = 0; SetState(STATE_RELEASE);