aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorTravis Howell2002-09-21 13:48:03 +0000
committerTravis Howell2002-09-21 13:48:03 +0000
commitf1a273e09240d6a439cccbe5dffa99a54cc43229 (patch)
tree010a738669c4ec193a0c0ef36913499c6f930eb7 /scumm
parenta2a3fb5636b3d12301490db715c5732f5e211915 (diff)
downloadscummvm-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
Diffstat (limited to 'scumm')
-rw-r--r--scumm/resource.cpp369
-rw-r--r--scumm/saveload.cpp3
-rw-r--r--scumm/scumm.h1
-rw-r--r--scumm/scummvm.cpp16
-rw-r--r--scumm/sound.cpp72
-rw-r--r--scumm/sound.h6
6 files changed, 450 insertions, 17 deletions
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();