aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorduck912 <350528965+Duck912@users.noreply.github.com>2026-10-31 01:45:56 -0400
committerDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 14:58:49 -0500
commite6c0a42d11f15e623c399d14454e5ae8e1a72942 (patch)
tree1a27d42db74ef26cf1efaea2a92538874a020c87 /src
parent681d50cd9cadf0b2205311dc20c84a9e774898d9 (diff)
audio_core: accept the Switch 2 audio renderer revision
Switch 2 titles send revision 16 with the 'REv' magic and use the voice crossfade fields. Without them GetWorkBufferSize failed with 0xc0299 and Fire Emblem: Fortune's Weave aborted (2153-1537). Ported from the Eden NS2 tree, keeping Eglantine's lenient revision compare. Assisted-by: Claude Opus 5.5 (debugging, porting and drafting) Signed-off-by: duck912 <350528965+Duck912@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/common/feature_support.h28
-rw-r--r--src/audio_core/renderer/behavior/behavior_info.cpp8
-rw-r--r--src/audio_core/renderer/behavior/behavior_info.h1
-rw-r--r--src/audio_core/renderer/behavior/info_updater.cpp9
4 files changed, 35 insertions, 11 deletions
diff --git a/src/audio_core/common/feature_support.h b/src/audio_core/common/feature_support.h
index 4585be45ef..d6571c0661 100644
--- a/src/audio_core/common/feature_support.h
+++ b/src/audio_core/common/feature_support.h
@@ -17,6 +17,16 @@
namespace AudioCore {
constexpr u32 CurrentRevision = 15;
+constexpr u32 NativeCurrentRevision = 16;
+
+constexpr bool IsNativeRevision(u32 revision) {
+ return (revision & 0xffffff) == Common::MakeMagic('R', 'E', 'v', '\0');
+}
+
+constexpr u32 EncodeRevision(u32 revision, bool native) {
+ return Common::MakeMagic('R', 'E', native ? 'v' : 'V',
+ static_cast<char>('0' + revision));
+}
enum class SupportTags {
CommandProcessingTimeEstimatorVersion4,
@@ -57,12 +67,15 @@ enum class SupportTags {
};
constexpr u32 GetRevisionNum(u32 user_revision) {
- if (user_revision >= 0x100) {
- user_revision -= Common::MakeMagic('R', 'E', 'V', '0');
- user_revision >>= 24;
+ if (user_revision < 0x100) {
+ return user_revision;
}
-
- return user_revision;
+ if (!IsNativeRevision(user_revision) &&
+ (user_revision & 0xffffff) != Common::MakeMagic('R', 'E', 'V', '\0')) {
+ return ~u32{0};
+ }
+ const u32 encoded = user_revision >> 24;
+ return encoded >= '0' ? encoded - '0' : ~u32{0};
};
constexpr bool CheckFeatureSupported(SupportTags tag, u32 user_revision) {
@@ -108,11 +121,12 @@ constexpr bool CheckFeatureSupported(SupportTags tag, u32 user_revision) {
return false;
}
user_revision = GetRevisionNum(user_revision);
- return (*feature).second <= user_revision;
+ return user_revision != ~u32{0} && (*feature).second <= user_revision;
}
constexpr bool CheckValidRevision(u32 user_revision) {
- return GetRevisionNum(user_revision) <= CurrentRevision;
+ return GetRevisionNum(user_revision) <=
+ (IsNativeRevision(user_revision) ? NativeCurrentRevision : CurrentRevision);
};
} // namespace AudioCore
diff --git a/src/audio_core/renderer/behavior/behavior_info.cpp b/src/audio_core/renderer/behavior/behavior_info.cpp
index 63b80c503a..983cfd5b85 100644
--- a/src/audio_core/renderer/behavior/behavior_info.cpp
+++ b/src/audio_core/renderer/behavior/behavior_info.cpp
@@ -16,8 +16,7 @@ u32 BehaviorInfo::GetProcessRevisionNum() const {
}
u32 BehaviorInfo::GetProcessRevision() const {
- return Common::MakeMagic('R', 'E', 'V',
- static_cast<char>(static_cast<u8>('0') + process_revision));
+ return EncodeRevision(process_revision, native_platform);
}
u32 BehaviorInfo::GetUserRevisionNum() const {
@@ -25,11 +24,12 @@ u32 BehaviorInfo::GetUserRevisionNum() const {
}
u32 BehaviorInfo::GetUserRevision() const {
- return Common::MakeMagic('R', 'E', 'V',
- static_cast<char>(static_cast<u8>('0') + user_revision));
+ return EncodeRevision(user_revision, native_platform);
}
void BehaviorInfo::SetUserLibRevision(const u32 user_revision_) {
+ native_platform = IsNativeRevision(user_revision_);
+ process_revision = native_platform ? NativeCurrentRevision : CurrentRevision;
user_revision = GetRevisionNum(user_revision_);
}
diff --git a/src/audio_core/renderer/behavior/behavior_info.h b/src/audio_core/renderer/behavior/behavior_info.h
index 757f163c5a..318d4e1ff4 100644
--- a/src/audio_core/renderer/behavior/behavior_info.h
+++ b/src/audio_core/renderer/behavior/behavior_info.h
@@ -400,6 +400,7 @@ public:
u32 process_revision;
/// User version
u32 user_revision{};
+ bool native_platform{};
/// Behaviour flags
Flags flags{};
/// Errors generated and reported during Update
diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp
index ca3eaece94..a8fbcf9730 100644
--- a/src/audio_core/renderer/behavior/info_updater.cpp
+++ b/src/audio_core/renderer/behavior/info_updater.cpp
@@ -122,12 +122,21 @@ Result InfoUpdater::UpdateVoices(VoiceContext& voice_context,
u8 flush_wave_buffer_count;
u16 reserved2;
VoiceInfo::Flags flags;
+ u8 reserved_after_flags;
SrcQuality src_quality;
+ u8 crossfade_curve;
u32 external_ctx;
u32 external_ctx_size;
u32 reserved3[2];
};
+ static_assert(sizeof(VoiceInParameterV2) == 0x188);
+ static_assert(offsetof(VoiceInParameterV2, crossfade_curve) == 0x177);
const auto* vin = reinterpret_cast<const VoiceInParameterV2*>(input + i * in_stride);
+ if (behaviour.GetUserRevisionNum() >= 16 && vin->in_use && vin->crossfade_curve != 0) {
+ LOG_ERROR(Service_Audio, "Unsupported voice biquad crossfade curve {}",
+ vin->crossfade_curve);
+ return Service::Audio::ResultInvalidUpdateInfo;
+ }
local_in.id = vin->id;
local_in.node_id = vin->node_id;
local_in.is_new = vin->is_new;