diff options
author | Colin Snover | 2017-06-16 12:57:24 -0500 |
---|---|---|
committer | Colin Snover | 2017-06-17 13:09:27 -0500 |
commit | e69507cc28ad5de480f12d9116624b7795738ece (patch) | |
tree | 285f6e0cf4f3e09ea1bac639ffb370e59780bb4f /engines | |
parent | 7334f33a3d1fdb172d8987093bd677aeb9382571 (diff) | |
download | scummvm-rg350-e69507cc28ad5de480f12d9116624b7795738ece.tar.gz scummvm-rg350-e69507cc28ad5de480f12d9116624b7795738ece.tar.bz2 scummvm-rg350-e69507cc28ad5de480f12d9116624b7795738ece.zip |
SCI32: Implement engine-accurate DPCM overflow behaviour
DPCM decompression algorithms in SSCI operate directly on 8- and
16-bit registers, so any sample that ends up being out-of-range
during decompression gets wrapped by the CPU, not clipped.
This does not fix any known problem with AUD files, but there are
some VMDs (e.g. GK2 5280.VMD) which are known to contain OOR
samples. Making this code more accurate should prevent trouble
with any other similar files.
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/sound/decoders/sol.cpp | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/engines/sci/sound/decoders/sol.cpp b/engines/sci/sound/decoders/sol.cpp index 121ffe400a..4b366ce9f4 100644 --- a/engines/sci/sound/decoders/sol.cpp +++ b/engines/sci/sound/decoders/sol.cpp @@ -54,13 +54,21 @@ static const byte tableDPCM8[8] = { 0, 1, 2, 3, 6, 10, 15, 21 }; * Decompresses one channel of 16-bit DPCM compressed audio. */ static void deDPCM16Channel(int16 *out, int16 &sample, uint8 delta) { + int32 nextSample = sample; if (delta & 0x80) { - sample -= tableDPCM16[delta & 0x7f]; + nextSample -= tableDPCM16[delta & 0x7f]; } else { - sample += tableDPCM16[delta]; + nextSample += tableDPCM16[delta]; } - sample = CLIP<int16>(sample, -32768, 32767); - *out = sample; + + // Emulating x86 16-bit signed register overflow + if (nextSample > 32767) { + nextSample -= 65536; + } else if (nextSample < -32768) { + nextSample += 65536; + } + + *out = sample = nextSample; } /** @@ -101,7 +109,6 @@ static void deDPCM8Nibble(int16 *out, uint8 &sample, uint8 delta) { } else { sample += tableDPCM8[delta & 7]; } - sample = CLIP<byte>(sample, 0, 255); *out = ((lastSample + sample) << 7) ^ 0x8000; } |