diff options
author | Travis Howell | 2002-09-21 13:48:03 +0000 |
---|---|---|
committer | Travis Howell | 2002-09-21 13:48:03 +0000 |
commit | f1a273e09240d6a439cccbe5dffa99a54cc43229 (patch) | |
tree | 010a738669c4ec193a0c0ef36913499c6f930eb7 | |
parent | a2a3fb5636b3d12301490db715c5732f5e211915 (diff) | |
download | scummvm-rg350-f1a273e09240d6a439cccbe5dffa99a54cc43229.tar.gz scummvm-rg350-f1a273e09240d6a439cccbe5dffa99a54cc43229.tar.bz2 scummvm-rg350-f1a273e09240d6a439cccbe5dffa99a54cc43229.zip |
Add the following patches:
[ 609649 ] Sound patch for GF_OLD256 games
[ 611997 ] RFC: Timer-based CD audio sync
svn-id: r4986
-rw-r--r-- | common/gameDetector.cpp | 2 | ||||
-rw-r--r-- | scumm/resource.cpp | 369 | ||||
-rw-r--r-- | scumm/saveload.cpp | 3 | ||||
-rw-r--r-- | scumm/scumm.h | 1 | ||||
-rw-r--r-- | scumm/scummvm.cpp | 16 | ||||
-rw-r--r-- | scumm/sound.cpp | 72 | ||||
-rw-r--r-- | scumm/sound.h | 6 |
7 files changed, 451 insertions, 18 deletions
diff --git a/common/gameDetector.cpp b/common/gameDetector.cpp index 2316331e73..22b5902e51 100644 --- a/common/gameDetector.cpp +++ b/common/gameDetector.cpp @@ -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, diff --git a/scumm/resource.cpp b/scumm/resource.cpp index cfbf4e7283..bef67b94a4 100644 --- a/scumm/resource.cpp +++ b/scumm/resource.cpp @@ -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) diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index 22add4a88a..80542caf0f 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -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); diff --git a/scumm/scumm.h b/scumm/scumm.h index 70fbea7751..384f8ca1b2 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -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(); diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index 19287b6164..2de4a1cdfb 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -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) { diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 2568edc606..252285fcec 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -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 diff --git a/scumm/sound.h b/scumm/sound.h index 773fc51787..a0c6af1725 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -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(); |