SCI: Added some of the missing pieces for speech support in CD games. It now partially works.

svn-id: r41146
This commit is contained in:
Walter van Niftrik 2009-06-03 18:43:22 +00:00
parent 0efe78d0f8
commit 6e079f7ea8
2 changed files with 107 additions and 38 deletions

View file

@ -1252,50 +1252,92 @@ bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &o
return false; return false;
} }
bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset) { bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) {
// KQ6 floppy // 65535.MAP structure:
// ========== // =========
// 65535.MAP contains 6-byte entries: // 6 byte entries:
// w nEntry // w nEntry
// dw offset // dw offset
// ending with 6 0xFFs
// haven't checked the CD version yet
// KQ6 CD // Other map files:
// ====== // ===============
// The other map files start with a 4-byte header and contain 7-byte entries: // Header:
// dw nEntry // dw baseOffset
// w unknown (offset? it can't be. Perhaps audio entry?) // Followed by 7 or 11-byte entries:
// b unknown (almost always 0, probably some sort of volume?) // b noun
// ending with 8 0xFFs // b verb
// b cond
// b seq
// tb cOffset (cumulative offset)
// w syncSize (iff seq has bits 7 and 6 set)
// w syncAscSize (iff seq has bits 7 and 6 set)
uint32 n; uint32 n;
offset = 0; offset = 0;
uint16 cur = 0;
int offs = (volume == 65535) ? 0 : 1;
if (_audioMapSCI11 && _audioMapSCI11->number != volume) { if (_audioMapSCI11 && _audioMapSCI11->number != volume) {
_resMgr->unlockResource(_audioMapSCI11, _audioMapSCI11->number, kResourceTypeMap); _resMgr->unlockResource(_audioMapSCI11, _audioMapSCI11->number, kResourceTypeMap);
_audioMapSCI11 = 0; _audioMapSCI11 = 0;
} }
if (!_audioMapSCI11) if (!_audioMapSCI11) {
_audioMapSCI11 = _resMgr->findResource(kResourceTypeMap, volume, 1); _audioMapSCI11 = _resMgr->findResource(kResourceTypeMap, volume, 1);
}
byte *ptr = _audioMapSCI11->data + ((volume == 65535) ? 0 : 4); byte *ptr = _audioMapSCI11->data;
while (cur < _audioMapSCI11->size) {
n = (volume == 65535) ? READ_UINT16(ptr) : TO_BE_32(READ_UINT32(ptr));
offset = (volume == 65535) ? READ_UINT32(ptr + 2) : READ_UINT16(ptr + 4); // TODO
if (n == audioNumber) { if (volume == 65535) {
// TODO: find out what these are while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) {
if (volume != 65535) n = READ_UINT16(ptr);
printf("audio entry found: %d %d %d\n", ptr[4], ptr[5], ptr[6]); ptr += 2;
return true;
if (n == 0xffff)
break;
offset = READ_UINT32(ptr);
ptr += 4;
if (n == audioNumber)
return true;
} }
} else {
offset = READ_UINT32(ptr);
ptr += 4;
ptr += 6 + offs; while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) {
cur += 6 + offs; n = READ_BE_UINT32(ptr);
ptr += 4;
if (n == 0xffffffff)
break;
offset += (READ_UINT16(ptr) | (ptr[2] << 16));
ptr += 3;
int syncSkip = 0;
if ((n & 0xc0) == 0xc0) {
n ^= 0xc0;
if (getSync) {
if (size)
*size = READ_UINT16(ptr);
} else {
syncSkip = READ_UINT16(ptr) + READ_UINT16(ptr + 2);
offset += syncSkip;
}
if (n == audioNumber)
return true;
ptr += 4;
} else {
if (n == audioNumber)
return !getSync;
}
offset -= syncSkip;
}
} }
return false; return false;
@ -1314,28 +1356,53 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16
return NULL; return NULL;
} }
audioStream->readByte(); // skip header size (1 byte), usually 0B (11 bytes) int headerSize = audioStream->readByte();
audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes)
*audioRate = audioStream->readUint16LE(); *audioRate = audioStream->readUint16LE();
audioFlags = audioStream->readByte(); audioFlags = audioStream->readByte();
if (audioFlags & kSolFlagCompressed) {
warning("ADPCM compressed SOL files are not supported yet");
return NULL;
}
// Convert the SOL stream flags to our own format // Convert the SOL stream flags to our own format
*flags = 0; *flags = 0;
if (audioFlags & kSolFlag16Bit) if (audioFlags & kSolFlag16Bit)
*flags |= Audio::Mixer::FLAG_16BITS; *flags |= Audio::Mixer::FLAG_16BITS;
if (!(audioFlags & kSolFlagIsSigned)) if ((audioFlags & kSolFlagCompressed) || !(audioFlags & kSolFlagIsSigned))
*flags |= Audio::Mixer::FLAG_UNSIGNED; *flags |= Audio::Mixer::FLAG_UNSIGNED;
*size = audioStream->readUint16LE(); *size = audioStream->readUint16LE();
// We assume that the sound data is raw PCM if (headerSize == 12)
byte *buffer = new byte[*size]; *size |= audioStream->readByte() << 16;
audioStream->read(buffer, *size);
byte *buffer;
if (audioFlags & kSolFlagCompressed) {
if (audioFlags & kSolFlag16Bit) {
warning("Unsupported DPCM mode");
return NULL;
}
buffer = new byte[*size * 2];
byte sample = 0x80;
for (uint i = 0; i < *size; i++) {
const int delta[] = {0, 1, 2, 3, 6, 10, 15, 21, -21, -15, -10, -6, -3, -2, -1, -0};
byte b = audioStream->readByte();
sample += delta[b >> 4];
buffer[i * 2] = sample;
sample += delta[b & 0xf];
buffer[i * 2 + 1] = sample;
}
*size *= 2;
} else {
// We assume that the sound data is raw PCM
buffer = new byte[*size];
audioStream->read(buffer, *size);
}
return buffer; return buffer;
} }
@ -1417,6 +1484,8 @@ Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 vol
audioFile->read(data, size); audioFile->read(data, size);
} else { } else {
data = readSOLAudio(audioFile, &size, &_audioRate, &flags); data = readSOLAudio(audioFile, &size, &_audioRate, &flags);
if (!data)
return NULL;
} }
audioFile->close(); audioFile->close();

View file

@ -342,7 +342,7 @@ private:
int _sciVersion; int _sciVersion;
bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size); bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size);
bool findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset); bool findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync = false, uint32 *size = NULL);
}; };
} // End of namespace Sci } // End of namespace Sci