aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorColin Snover2017-06-16 12:57:24 -0500
committerColin Snover2017-06-17 13:09:27 -0500
commite69507cc28ad5de480f12d9116624b7795738ece (patch)
tree285f6e0cf4f3e09ea1bac639ffb370e59780bb4f /engines
parent7334f33a3d1fdb172d8987093bd677aeb9382571 (diff)
downloadscummvm-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.cpp17
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;
}