Skip to content

Commit

Permalink
SCI: Fix detection of end of audio map & entry size in SCI32
Browse files Browse the repository at this point in the history
Torin RU map 38140 has an unusual terminator entry; instead of a
normal terminating entry of 11 FFs, its terminating entry is
03 FF FF FF FF C4 36 01 FF FF FF. So, two changes are made:

1. The end-of-map check is now the same as in SSCI1.1+ and only
   checks that the final byte of the Audio36 tuple is 0xFF,
   instead of the entire tuple;
2. The unneeded entry size heuristic has been turned off for
   all SCI32 games.

A quick check of the English versions of LB2CD, EQ1CD, SQ4CD, and
KQ6CD, as well as all English SCI32 games, indicates that this
approach seems to be working correctly.

Fixes Trac#10188.
  • Loading branch information
csnover committed Sep 20, 2017
1 parent a7479b4 commit 1515bb3
Showing 1 changed file with 30 additions and 10 deletions.
40 changes: 30 additions & 10 deletions engines/sci/resource_audio.cpp
Expand Up @@ -339,13 +339,19 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {

SciSpan<const byte>::const_iterator ptr = mapRes->cbegin();

// Heuristic to detect entry size
uint32 entrySize = 0;
for (int i = mapRes->size() - 1; i >= 0; --i) {
if (ptr[i] == 0xff)
entrySize++;
else
break;
if (_volVersion >= kResVersionSci2) {
// The heuristic size detection is incompatible with at least Torin RU,
// which is fine because it is not needed for SCI32
entrySize = 11;
} else {
// Heuristic to detect entry size
for (int i = mapRes->size() - 1; i >= 0; --i) {
if (ptr[i] == 0xff)
entrySize++;
else
break;
}
}

if (map->_mapNumber == 65535) {
Expand Down Expand Up @@ -419,20 +425,34 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {

disposeVolumeFileStream(stream, src);
} else {
bool isEarly = (entrySize != 11);
// EQ1CD & SQ4CD are "early" games; KQ6CD and all SCI32 are "late" games
const bool isEarly = (entrySize != 11);

if (!isEarly) {
offset = ptr.getUint32LE();
ptr += 4;
}

enum {
kRaveFlag = 0x40,
kSyncFlag = 0x80,
kEndOfMapFlag = 0xFF
};

while (ptr != mapRes->cend()) {
uint32 n = ptr.getUint32BE();
uint32 syncSize = 0;
ptr += 4;

if (n == 0xffffffff)
// Checking the entire tuple breaks Torin RU and is not how SSCI
// works
if ((n & kEndOfMapFlag) == kEndOfMapFlag) {
const uint32 bytesLeft = mapRes->cend() - ptr;
if (bytesLeft >= entrySize) {
warning("End of %s reached, but %u entries remain", mapResId.toString().c_str(), bytesLeft / entrySize);
}
break;
}

if (isEarly) {
offset = ptr.getUint32LE();
Expand All @@ -442,7 +462,7 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
ptr += 3;
}

if (isEarly || (n & 0x80)) {
if (isEarly || (n & kSyncFlag)) {
syncSize = ptr.getUint16LE();
ptr += 2;

Expand All @@ -455,7 +475,7 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {

// Checking for this 0x40 flag breaks at least Laura Bow 2 CD 1.1
// map 448
if (g_sci->getGameId() == GID_KQ6 && (n & 0x40)) {
if (g_sci->getGameId() == GID_KQ6 && (n & kRaveFlag)) {
// This seems to define the size of raw lipsync data (at least
// in KQ6 CD Windows).
uint32 kq6HiresSyncSize = ptr.getUint16LE();
Expand Down

0 comments on commit 1515bb3

Please sign in to comment.