Merge pull request #5024 from jroweboy/temp-hle-audio-fix
Prevent out of memory errors when the game passes in an improper length value
This commit is contained in:
commit
5fd1ff08d7
1 changed files with 50 additions and 28 deletions
|
@ -171,6 +171,20 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
|
||||||
|
|
||||||
if (config.embedded_buffer_dirty) {
|
if (config.embedded_buffer_dirty) {
|
||||||
config.embedded_buffer_dirty.Assign(0);
|
config.embedded_buffer_dirty.Assign(0);
|
||||||
|
// HACK
|
||||||
|
// Luigi's Mansion Dark Moon configures the embedded buffer with an extremely large value
|
||||||
|
// for length, causing the Dequeue method to allocate a buffer of that size, eating up all
|
||||||
|
// of the users RAM. It appears that the game is calculating the length of the sample by
|
||||||
|
// using some value from the DSP and subtracting another value, which causes it to
|
||||||
|
// underflow. We need to investigate further into what value the game is reading from and
|
||||||
|
// fix that, but as a stop gap, we can just prevent these underflowed values from playing in
|
||||||
|
// the mean time
|
||||||
|
if (static_cast<s32>(config.length) < 0) {
|
||||||
|
LOG_ERROR(Audio_DSP,
|
||||||
|
"Skipping embedded buffer sample! Game passed in improper value for length. "
|
||||||
|
"addr {:X} length {:X}",
|
||||||
|
config.physical_address, config.length);
|
||||||
|
} else {
|
||||||
state.input_queue.emplace(Buffer{
|
state.input_queue.emplace(Buffer{
|
||||||
config.physical_address,
|
config.physical_address,
|
||||||
config.length,
|
config.length,
|
||||||
|
@ -185,6 +199,7 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
|
||||||
play_position,
|
play_position,
|
||||||
false,
|
false,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
LOG_TRACE(Audio_DSP, "enqueuing embedded addr={:#010x} len={} id={} start={}",
|
LOG_TRACE(Audio_DSP, "enqueuing embedded addr={:#010x} len={} id={} start={}",
|
||||||
config.physical_address, config.length, config.buffer_id,
|
config.physical_address, config.length, config.buffer_id,
|
||||||
static_cast<u32>(config.play_position));
|
static_cast<u32>(config.play_position));
|
||||||
|
@ -201,6 +216,12 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
|
||||||
for (std::size_t i = 0; i < 4; i++) {
|
for (std::size_t i = 0; i < 4; i++) {
|
||||||
if (config.buffers_dirty & (1 << i)) {
|
if (config.buffers_dirty & (1 << i)) {
|
||||||
const auto& b = config.buffers[i];
|
const auto& b = config.buffers[i];
|
||||||
|
if (static_cast<s32>(b.length) < 0) {
|
||||||
|
LOG_ERROR(Audio_DSP,
|
||||||
|
"Skipping buffer queue sample! Game passed in improper value for "
|
||||||
|
"length. addr {:X} length {:X}",
|
||||||
|
b.physical_address, b.length);
|
||||||
|
} else {
|
||||||
state.input_queue.emplace(Buffer{
|
state.input_queue.emplace(Buffer{
|
||||||
b.physical_address,
|
b.physical_address,
|
||||||
b.length,
|
b.length,
|
||||||
|
@ -215,6 +236,7 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
|
||||||
{}, // 0 in u32_dsp
|
{}, // 0 in u32_dsp
|
||||||
false,
|
false,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
LOG_TRACE(Audio_DSP, "enqueuing queued {} addr={:#010x} len={} id={}", i,
|
LOG_TRACE(Audio_DSP, "enqueuing queued {} addr={:#010x} len={} id={}", i,
|
||||||
b.physical_address, b.length, b.buffer_id);
|
b.physical_address, b.length, b.buffer_id);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue