Add the following patches:

[ 609649 ] Sound patch for GF_OLD256 games
[ 611997 ] RFC: Timer-based CD audio sync

svn-id: r4986
This commit is contained in:
Travis Howell 2002-09-21 13:48:03 +00:00
parent a2a3fb5636
commit f1a273e092
7 changed files with 451 additions and 18 deletions

View File

@ -363,7 +363,7 @@ static const VersionSettings version_settings[] = {
/* Scumm Version 3 */
{"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3_256, 3, 0, 22,
GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_NO_SCALLING},
GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_NO_SCALLING | GF_ADLIB_DEFAULT},
{"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, 0, 0,
GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_AUDIOTRACKS | GF_NO_SCALLING},
{"loom", "Loom", GID_LOOM, 3, 5, 40,

View File

@ -530,6 +530,8 @@ int Scumm::loadResource(int type, int idx)
size = _fileHandle.readDwordLE();
tag = _fileHandle.readWordLE();
_fileHandle.seek(-6, SEEK_CUR);
if (type == rtSound)
return readSoundResourceSmallHeader(type, idx);
} else {
if (type == rtSound) {
_fileHandle.readDwordLE();
@ -730,6 +732,373 @@ int Scumm::readSoundResource(int type, int idx)
return 0;
}
// FIXME: some default MIDI instruments for INDY3/MI1
static char OLD256_MIDI_HACK[] =
// 0
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x00\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x00" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb0\x07\x64" // Controller 7 = 100
// 1
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x01\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x01" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb1\x07\x64" // Controller 7 = 100
// 2
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x02\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x02" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb2\x07\x64" // Controller 7 = 100
// 3
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x03\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x03" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb3\x07\x64" // Controller 7 = 100
// 4
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x04\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x04" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb4\x07\x64" // Controller 7 = 100
// 5
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x05\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x05" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb5\x07\x64" // Controller 7 = 100
// 6
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x06\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x06" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb6\x07\x64" // Controller 7 = 100
// 7
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x07\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x07" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb7\x07\x64" // Controller 7 = 100
// 8
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x08\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x08" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb8\x07\x64" // Controller 7 = 100
// 9
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x09\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x09" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xb9\x07\x64" // Controller 7 = 100
// Channels after 9 realy necessary ?!?
// A
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x0A\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x0A" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xbA\x07\x64" // Controller 7 = 100
// B
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x0B\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x0B" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xbB\x07\x64" // Controller 7 = 100
// C
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x0C\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x0C" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xbC\x07\x64" // Controller 7 = 100
// D
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x0D\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x0D" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xbD\x07\x64" // Controller 7 = 100
// E
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x0E\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x0E" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xbE\x07\x64" // Controller 7 = 100
// F
"\x00\xf0\x14\x7d\x00" // sysex 00: part on/off
"\x0F\x00\x03" // part/channel
"\x00\x00\x07\x0f\x00\x00\x08\x00\x00\x00\x00\x02\x00\x00\xf7"
"\x04\xf0\x41\x7d\x10" // sysex 16: set instrument
"\x0F" // part/channel
"\x01\x06\x02\x0a\x08\x09\x0d\x08\x04\x04"
"\x04\x06\x02\x02\x03\x07\x0f\x0d"
"\x05\x04\x0c\x00\x03\x0a\x01\x00"
"\x00\x00\x01\x01\x0e\x00\x02\x02"
"\x01\x00\x01\x00\x01\x02\x00\x0a"
"\x08\x00\x00\x00\x01\x02\x04\x00"
"\x06\x02\x00\x00\x04\x00\x03\x02"
"\x04\x00\x00\xf7"
"\x00\xbF\x07\x64"; // Controller 7 = 100
int Scumm::readSoundResourceSmallHeader(int type, int idx)
{
uint32 pos, total_size, size, dw, tag;
uint32 best_size = 0, best_offs = 0;
byte *ptr, *track;
uint16 ticks, skip;
debug(4, "readSoundResourceSmallHeader(%s,%d)", resTypeFromId(type), idx);
//if (_rescache->readResource(roomNr, type, idx))
// return 1;
total_size = size = _fileHandle.readDwordLE();
tag = _fileHandle.readWordLE();
debug(4, " tag='%c%c', size=%d",
(char) (tag & 0xff),
(char) ((tag >> 8) & 0xff), size);
pos = 6;
while (pos < total_size) {
size = _fileHandle.readDwordLE();
tag = _fileHandle.readWordLE();
debug(4, " tag='%c%c', size=%d",
(char) (tag & 0xff),
(char) ((tag >> 8) & 0xff), size);
pos += size;
// MI1 and Indy3 uses one or more nested SO resources, which contains AD and WA
// resources.
if ((tag == 0x4441) && !(best_offs)) { // AD
best_size = size;
best_offs = _fileHandle.pos();
} else { // other AD, WA and nested SO resources
if (tag == 0x4F53) {
pos -= size;
size = 6;
pos += 6;
}
}
_fileHandle.seek(size - 6, SEEK_CUR);
}
// AD resources have a header, instrument definitions and one MIDI track.
// We build an 'ADL ' resource from that:
// 8 bytes resource header
// 16 bytes MDhd header
// 14 bytes MThd header
// 8 bytes MTrk header
// 7 MIDI speed event
// + some default instruments
// TODO: - make some real MIDI instrument definitions
// - no sound looping
// - proper handling of the short AD resources format
// - check the LE/BE handling for platforms other than PC
if (best_offs != 0) {
_fileHandle.seek(best_offs - 6, SEEK_SET);
ptr = createResource(type, idx, best_size);
_fileHandle.read(ptr, best_size);
ticks = READ_BE_UINT16(ptr + 9);
size = best_size;
if (size < 0x98) {
// FIXME: OLD256 music file w/o instruments
// perhaps we should use then the other "WA" resource in the "SO" resource
// and play it raw
skip = 0x0a; // let's give it a try
} else {
skip = 0x98;
}
ptr += skip; // size + instruments
size -= skip; // drop instruments for now
CHECK_HEAP track = (byte *)calloc(size, 1);
if (track == NULL) {
error("Out of memory while allocating %d", size);
}
memcpy(track, ptr, size); // saving MIDI track data
nukeResource(type, idx);
total_size = 8 + 16 + 14 + 8 + 7 + sizeof(OLD256_MIDI_HACK) - 1 + size;
ptr = createResource(type, idx, total_size);
memcpy(ptr, "ADL ", 4); ptr += 4;
dw = READ_BE_UINT32(&total_size);
memcpy(ptr, &dw, 4); ptr += 4;
memcpy(ptr, "MDhd", 4); ptr += 4;
ptr[0] = 0; ptr[1] = 0; ptr[2] = 0; ptr[3] = 8;
ptr += 4;
dw = 0;
memcpy(ptr, &dw, 4); ptr += 4;
memcpy(ptr, &dw, 4); ptr += 4;
memcpy(ptr, "MThd", 4); ptr += 4;
ptr[0] = 0; ptr[1] = 0; ptr[2] = 0; ptr[3] = 6;
ptr += 4;
ptr[0] = 0; ptr[1] = 0; ptr[2] = 0; ptr[3] = 1; // MIDI format 0 with 1 track
ptr += 4;
memcpy(ptr, &ticks, 2); ptr += 2; // FIXME: care of BE/LE needed ?
memcpy(ptr, "MTrk", 4); ptr += 4;
*ptr++ = ((sizeof(OLD256_MIDI_HACK) - 1 + size + 7) >> 24) & 0xFF;
*ptr++ = ((sizeof(OLD256_MIDI_HACK) - 1 + size + 7) >> 16) & 0xFF;
*ptr++ = ((sizeof(OLD256_MIDI_HACK) - 1 + size + 7) >> 8) & 0xFF;
*ptr++ = ((sizeof(OLD256_MIDI_HACK) - 1 + size + 7) ) & 0xFF;
// speed hacks
dw = 1100000 - (ticks * 10);
if ((dw > 900000) || (dw < 200000))
dw = 500000; // for sanity
debug(4, " ticks = %d, speed = %ld", ticks, dw);
memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4;
*ptr++ = (dw >> 16) & 0xFF;
*ptr++ = (dw >> 8) & 0xFF;
*ptr++ = dw & 0xFF;
memcpy(ptr, OLD256_MIDI_HACK, sizeof(OLD256_MIDI_HACK) - 1);
ptr += sizeof(OLD256_MIDI_HACK) - 1;
memcpy(ptr, track, size);
free(track);
//hexdump(ptr = getResourceAddress(type, idx), 32);
return 1;
}
res.roomoffs[type][idx] = 0xFFFFFFFF;
return 0;
}
int Scumm::getResourceRoomNr(int type, int idx)
{
if (type == rtRoom)

View File

@ -159,6 +159,9 @@ bool Scumm::loadState(int slot, bool compat)
initBGBuffers(_scrHeight);
if ((_features & GF_AUDIOTRACKS) && _vars[VAR_MI1_TIMER] > 0)
_sound->startCDTimer();
CHECK_HEAP debug(1, "State loaded from '%s'", filename);

View File

@ -595,6 +595,7 @@ public:
int loadResource(int type, int i);
int getResourceRoomNr(int type, int index);
int readSoundResource(int type, int index);
int readSoundResourceSmallHeader(int type, int index);
void setResourceCounter(int type, int index, byte flag);
void validateResource(const char *str, int type, int index);
void increaseResourceCounter();

View File

@ -340,8 +340,6 @@ void Scumm::checkRange(int max, int min, int no, const char *str)
int Scumm::scummLoop(int delta)
{
static int counter = 0;
#ifndef _WIN32_WCE
if (_debugger)
_debugger->on_frame();
@ -380,18 +378,8 @@ int Scumm::scummLoop(int delta)
_vars[VAR_MOUSE_Y] = mouse.y;
_vars[VAR_DEBUGMODE] = _debugMode;
if (_features & GF_AUDIOTRACKS) {
if (delta) {
if (delta == 1) {
// Better sync with the Loom CD intro
_vars[VAR_MI1_TIMER]++;
} else if (++counter != 2)
_vars[VAR_MI1_TIMER] += 5;
else {
counter = 0;
_vars[VAR_MI1_TIMER] += 6;
}
}
if (_features & GF_AUDIOTRACKS) {
_vars[VAR_MI1_TIMER] = _sound->readCDTimer();
} else if (_features & GF_OLD256) {
if(tempMusic == 3) {

View File

@ -175,6 +175,8 @@ void Sound::playSound(int sound) {
int size;
int rate;
debug(3,"playSound #%d (room %d)",
sound, _scumm->getResourceRoomNr(rtSound, sound));
ptr = _scumm->getResourceAddress(rtSound, sound);
if (ptr) {
if (READ_UINT32_UNALIGNED(ptr) == MKID('SOUN')) {
@ -228,6 +230,10 @@ void Sound::playSound(int sound) {
}
return;
}
else if (READ_UINT32_UNALIGNED(ptr) == MKID('ADL ')) {
// played as MIDI, just to make perhaps the later use
// of WA possible (see "else if" with GF_OLD256 below)
}
// Support for sampled sound effects in Monkey1 and Monkey2
else if (READ_UINT32_UNALIGNED(ptr) == MKID('SBL ')) {
debug(2, "Using SBL sound effect");
@ -365,9 +371,6 @@ void Sound::playSound(int sound) {
return;
}
if (_scumm->_gameId == GID_MONKEY_VGA)
return; /* FIXME */
}
IMuse *se = _scumm->_imuse;
@ -667,6 +670,14 @@ void Sound::pauseSounds(bool pause) {
_soundsPaused = pause;
_scumm->_mixer->pause(pause);
if ((_scumm->_features & GF_AUDIOTRACKS) && _scumm->_vars[_scumm->VAR_MI1_TIMER] > 0) {
if (pause)
stopCDTimer();
else
startCDTimer();
}
}
int Sound::startSfxSound(File *file, int file_size) {
@ -1028,16 +1039,71 @@ int Sound::playSfxSound_MP3(void *sound, uint32 size) {
return -1;
}
// We use a real timer in an attempt to get better sync with CD tracks. This is
// necessary for games like Loom CD.
static void cd_timer_handler(void *ptr)
{
Scumm *scumm = (Scumm *) ptr;
// Maybe I could simply update _vars[VAR_MI1_TIMER] directly here, but
// I don't feel comfortable just doing that from what might be a
// separate thread. If someone tells me it's safe, I'll make the
// change right away.
// FIXME: Turn off the timer when it's no longer needed. In theory, it
// should be possible to check with pollCD(), but since CD sound isn't
// properly restarted when reloading a saved game, I don't dare to.
scumm->_sound->_cd_timer_value += 6;
}
int Sound::readCDTimer()
{
return _cd_timer_value;
}
void Sound::startCDTimer()
{
int timer_interval;
// The timer interval has been tuned for Loom CD and the Monkey 1
// intro. I have to use 100 for Loom, or there will be a nasty stutter
// when Chaos first appears, and I have to use 101 for Monkey 1 or the
// intro music will be cut short.
if (_scumm->_gameId == GID_LOOM256)
timer_interval = 100;
else
timer_interval = 101;
_scumm->_timer->releaseProcedure(&cd_timer_handler);
_cd_timer_value = _scumm->_vars[_scumm->VAR_MI1_TIMER];
_scumm->_timer->installProcedure(&cd_timer_handler, timer_interval);
}
void Sound::stopCDTimer()
{
_scumm->_timer->releaseProcedure(&cd_timer_handler);
}
void Sound::playCDTrack(int track, int num_loops, int start, int delay)
{
#ifdef COMPRESSED_SOUND_FILE
if (playMP3CDTrack(track, num_loops, start, delay) == -1)
#endif
_scumm->_system->play_cdrom(track, num_loops, start, delay);
// Start the timer after starting the track. Starting an MP3 track is
// almost instantaneous, but a CD player may take some time. Hopefully
// play_cdrom() will block during that delay.
startCDTimer();
}
void Sound::stopCD()
{
stopCDTimer();
#ifdef COMPRESSED_SOUND_FILE
if (stopMP3CD() == -1)
#endif

View File

@ -23,6 +23,7 @@
#include "scummsys.h"
#include "sound/mixer.h"
#include "common/timer.h"
class Scumm;
class File;
@ -88,6 +89,7 @@ public:
#endif
int _cd_timer_value;
bool _soundsPaused;
int16 _sound_volume_master, _sound_volume_music, _sound_volume_sfx;
byte _sfxMode;
@ -124,6 +126,10 @@ public:
int playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned);
int playSfxSound_MP3(void *sound, uint32 size);
int readCDTimer();
void startCDTimer();
void stopCDTimer();
void playCDTrack(int track, int num_loops, int start, int delay);
void stopCD();
int pollCD();