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:
parent
0efe78d0f8
commit
6e079f7ea8
2 changed files with 107 additions and 38 deletions
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue