mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
sceMp3LowLevelDecode: Don't require room for 1152 samples
Since b1ffcde9fc the output buffer had to hold 1152 stereo samples, but
an MPEG-2 or 2.5 frame makes 576, so a buffer near the end of memory
that fits the frame failed. When the buffer can't take the biggest
frame, decode aside and copy only what the frame made.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
77fed58257
commit
41a02ffcb3
1 file changed
+15
-4
+15
-4
@@ -759,20 +759,31 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed
|
||||
return hleLogError(Log::ME, -1, "invalid address in args");
|
||||
}
|
||||
|
||||
// A frame is at most 1152 stereo samples, and the decoder is handed up to 4096 bytes.
|
||||
if (!Memory::IsValidRange(samplesAddr, 1152 * 2 * 2) || !Memory::IsValidRange(sourceBytesConsumedAddr, 4) || !Memory::IsValidRange(sampleBytesAddr, 4)) {
|
||||
if (!Memory::IsValidRange(sourceBytesConsumedAddr, 4) || !Memory::IsValidRange(sampleBytesAddr, 4)) {
|
||||
return hleLogError(Log::ME, -1, "invalid address in args");
|
||||
}
|
||||
const u8 *inbuff = Memory::GetPointerWriteUnchecked(sourceAddr);
|
||||
int16_t *outbuf = (int16_t *)Memory::GetPointerWriteUnchecked(samplesAddr);
|
||||
// The decoder is handed up to 4096 bytes.
|
||||
const int inBytes = (int)Memory::ClampValidSizeAt(sourceAddr, 4096);
|
||||
|
||||
|
||||
// A frame is at most 1152 stereo samples, but an MPEG-2 or 2.5 one is 576. When the game's buffer
|
||||
// can't take the biggest, decode aside and copy only what this frame made.
|
||||
constexpr u32 maxFrameBytes = 1152 * 2 * 2;
|
||||
const u32 outRoom = Memory::ClampValidSizeAt(samplesAddr, maxFrameBytes);
|
||||
int16_t aside[1152 * 2];
|
||||
int outSamples = 0;
|
||||
int inbytesConsumed = 0;
|
||||
if (!ctx->decoder->Decode(inbuff, inBytes, &inbytesConsumed, 2, outbuf, &outSamples)) {
|
||||
if (!ctx->decoder->Decode(inbuff, inBytes, &inbytesConsumed, 2, outRoom == maxFrameBytes ? outbuf : aside, &outSamples)) {
|
||||
WARN_LOG(Log::ME, "sceMp3LowLevelDecode: Decode failed");
|
||||
}
|
||||
int outBytes = outSamples * sizeof(int16_t) * 2;
|
||||
if (outRoom != maxFrameBytes) {
|
||||
if ((u32)outBytes > outRoom) {
|
||||
return hleLogError(Log::ME, -1, "output buffer too small for the frame");
|
||||
}
|
||||
memcpy(outbuf, aside, outBytes);
|
||||
}
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outBytes, "Mp3LowLevelDecode");
|
||||
|
||||
Memory::WriteOrException_U32(inbytesConsumed, sourceBytesConsumedAddr);
|
||||
|
||||
Reference in new issue
Block a user