aboutsummaryrefslogtreecommitdiff
path: root/scumm/resource.cpp
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/resource.cpp
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/resource.cpp')
-rw-r--r--scumm/resource.cpp369
1 files changed, 369 insertions, 0 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)