aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorTravis Howell2003-08-05 05:21:57 +0000
committerTravis Howell2003-08-05 05:21:57 +0000
commit8bf012d966013a12e7cd0cf797b672f6593f357f (patch)
tree57b8d6a1ce7e952f06a78ec2c96c5e02eae689ad /scumm
parent1eaf41eda40f1777a5e99c19a027ea025cbaeb4c (diff)
downloadscummvm-rg350-8bf012d966013a12e7cd0cf797b672f6593f357f.tar.gz
scummvm-rg350-8bf012d966013a12e7cd0cf797b672f6593f357f.tar.bz2
scummvm-rg350-8bf012d966013a12e7cd0cf797b672f6593f357f.zip
Add adlib music improvements for indy3/monkeyega/monkeyvga and cleanups from patch #770862
svn-id: r9480
Diffstat (limited to 'scumm')
-rw-r--r--scumm/resource.cpp604
-rw-r--r--scumm/scumm.h2
-rw-r--r--scumm/scummvm.cpp6
-rw-r--r--scumm/sound.cpp2
4 files changed, 272 insertions, 342 deletions
diff --git a/scumm/resource.cpp b/scumm/resource.cpp
index b1ea5ae15a..aa190c8bbf 100644
--- a/scumm/resource.cpp
+++ b/scumm/resource.cpp
@@ -649,7 +649,6 @@ int Scumm::loadResource(int type, int idx) {
size = _fileHandle.readUint32LE();
tag = _fileHandle.readUint16LE();
_fileHandle.seek(-6, SEEK_CUR);
- /* FIXME */
if ((type == rtSound) && !(_features & GF_AMIGA) && !(_features & GF_FMTOWNS)) {
return readSoundResourceSmallHeader(type, idx);
}
@@ -889,166 +888,269 @@ 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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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\x01\x01\x00"
- "\x00\x00\x01\x01\x0e\x00\x02\x02"
- "\x01\x00\x01\x00\x01\x02\x00\x01"
- "\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
+// Adlib MIDI-SYSEX to set MIDI instruments for small header games.
+static byte ADLIB_INSTR_MIDI_HACK[95] = {
+ 0x00, 0xf0, 0x14, 0x7d, 0x00, // sysex 00: part on/off
+ 0x00, 0x00, 0x03, // part/channel (offset 5)
+ 0x00, 0x00, 0x07, 0x0f, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf7,
+ 0x04, 0xf0, 0x41, 0x7d, 0x10, // sysex 16: set instrument
+ 0x00, // part/channel (offset 28)
+ 0x01, 0x06, 0x02, 0x0a, 0x08, 0x09, 0x0d, 0x08, 0x04, 0x04,
+ 0x04, 0x06, 0x02, 0x02, 0x03, 0x07, 0x0f, 0x0d,
+ 0x05, 0x04, 0x0c, 0x00, 0x03, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x0e, 0x00, 0x02, 0x02,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x01,
+ 0x08, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00,
+ 0x06, 0x02, 0x00, 0x00, 0x04, 0x00, 0x03, 0x02,
+ 0x04, 0x00, 0x00, 0xf7,
+ 0x00, 0xb0, 0x07, 0x64 // Controller 7 = 100 (offset 92)
+};
+
+int Scumm::convertADResource(int type, int idx, byte * src_ptr, int size) {
+
+ byte * ptr;
+ byte ticks, play_once;
+ byte music_type, num_instr;
+ byte *channel, *instr, *track;
+ int i, ch;
+
+ src_ptr += 2;
+ size -= 2;
+ music_type = *(src_ptr); // 0x80: is music; otherwise not.
+ if (music_type != 0x80) {
+ // It's an SFX; we don't know how to handle those yet
+ debug(4, "Sound %d not played, format not yet supported", idx);
+ nukeResource(type, idx);
+ res.roomoffs[type][idx] = 0xFFFFFFFF;
+ return 0;
+ }
+
+ // The "speed" of the song
+ ticks = *(src_ptr + 1);
+
+ // Flag that tells us whether we should loop the song (0) or play it only once (1)
+ play_once = *(src_ptr + 2);
+
+ // Number of instruments used
+ num_instr = *(src_ptr + 8); // Normally 8
+
+ // copy the pointer to instrument data
+ channel = src_ptr + 9;
+ instr = src_ptr + 0x11;
+
+ // skip over the rest of the header and copy the MIDI data into a buffer
+ src_ptr += 0x11 + 8 * 16;
+ size -= 0x11 + 8 * 16;
+
+ CHECK_HEAP
+
+ track = src_ptr;
+
+ int total_size = 8 + 16 + 14 + 8 + 7 + 8*sizeof(ADLIB_INSTR_MIDI_HACK) + size;
+ total_size += 24; // Up to 24 additional bytes are needed for the jump sysex
+
+ ptr = createResource(type, idx, total_size);
+ memcpy(ptr, "ADL ", 4); ptr += 4;
+ uint32 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;
+ memset(ptr, 0, 8), ptr += 8;
+ 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;
+
+ // We will ignore the PPQN in the original resource, because
+ // it's invalid anyway. We use a constant PPQN of 480.
+ // memcpy(ptr, &ticks, 2); ptr += 2;
+ *ptr++ = 480 >> 8;
+ *ptr++ = 480 & 0xFF;
+
+ memcpy(ptr, "MTrk", 4); ptr += 4;
+ dw = READ_BE_UINT32(&total_size);
+ memcpy(ptr, &dw, 4); ptr += 4;
+
+ // Conver the ticks into a MIDI tempo.
+ dw = (500000 * 256) / ticks;
+ debug(4, " ticks = %d, speed = %ld", ticks, dw);
+
+ // Write a tempo change SysEx
+ memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4;
+ *ptr++ = (byte)((dw >> 16) & 0xFF);
+ *ptr++ = (byte)((dw >> 8) & 0xFF);
+ *ptr++ = (byte)(dw & 0xFF);
+
+ // Copy our hardcoded instrument table into it
+ // Then, convert the instrument table as given in this song resource
+ // And write it *over* the hardcoded table.
+ // Note: we deliberately.
+
+ /* now fill in the instruments */
+ for (i = 0; i < num_instr; i++) {
+ ch = channel[i] - 1;
+
+ debug(4, "Sound %d: instrument %d on channel %d.",
+ idx, i, ch);
+
+ memcpy(ptr, ADLIB_INSTR_MIDI_HACK,
+ sizeof(ADLIB_INSTR_MIDI_HACK));
+
+ ptr[5] += ch;
+ ptr[28] += ch;
+ ptr[92] += ch;
+
+ /* flags_1 */
+ ptr[30 + 0] = (instr[i * 16 + 3] >> 4) & 0xf;
+ ptr[30 + 1] = instr[i * 16 + 3] & 0xf;
+
+ /* oplvl_1 */
+ ptr[30 + 2] = (instr[i * 16 + 4] >> 4) & 0xf;
+ ptr[30 + 3] = instr[i * 16 + 4] & 0xf;
+
+ /* atdec_1 */
+ ptr[30 + 4] = ((~instr[i * 16 + 5]) >> 4) & 0xf;
+ ptr[30 + 5] = (~instr[i * 16 + 5]) & 0xf;
+
+ /* sustrel_1 */
+ ptr[30 + 6] = ((~instr[i * 16 + 6]) >> 4) & 0xf;
+ ptr[30 + 7] = (~instr[i * 16 + 6]) & 0xf;
+
+ /* waveform_1 */
+ ptr[30 + 8] = (instr[i * 16 + 7] >> 4) & 0xf;
+ ptr[30 + 9] = instr[i * 16 + 7] & 0xf;
+
+ /* flags_2 */
+ ptr[30 + 10] = (instr[i * 16 + 8] >> 4) & 0xf;
+ ptr[30 + 11] = instr[i * 16 + 8] & 0xf;
+
+ /* oplvl_2 */
+ ptr[30 + 12] = (instr[i * 16 + 9] >> 4) & 0xf;
+ ptr[30 + 13] = instr[i * 16 + 9] & 0xf;
+
+ /* atdec_2 */
+ ptr[30 + 14] = ((~instr[i * 16 + 10]) >> 4) & 0xf;
+ ptr[30 + 15] = (~instr[i * 16 + 10]) & 0xf;
+
+ /* sustrel_2 */
+ ptr[30 + 16] = ((~instr[i * 16 + 11]) >> 4) & 0xf;
+ ptr[30 + 17] = (~instr[i * 16 + 11]) & 0xf;
+
+ /* waveform_2 */
+ ptr[30 + 18] = (instr[i * 16 + 12] >> 4) & 0xf;
+ ptr[30 + 19] = instr[i * 16 + 12] & 0xf;
+
+ /* feedback */
+ ptr[30 + 20] = (instr[i * 16 + 2] >> 4) & 0xf;
+ ptr[30 + 21] = instr[i * 16 + 2] & 0xf;
+ ptr += sizeof(ADLIB_INSTR_MIDI_HACK);
+ }
+
+ *ptr++ = 0; // delay 0;
+
+ // Now copy the actual music data
+ memcpy(ptr, track, size);
+ ptr += size;
+
+ if (!play_once) {
+ // The song is meant to be looped. We achieve this by inserting just
+ // before the song end a jump to the song start. More precisely we abuse
+ // a S&M sysex, "maybe_jump" to achieve this effect. We could also
+ // use a set_loop sysex, but it's a bit longer, a little more complicated,
+ // and has no advantage either.
+
+ // First, find the track end
+ byte *end = ptr;
+ ptr -= size;
+ for (; ptr < end; ptr++) {
+ if (*ptr == 0xff && *(ptr + 1) == 0x2f)
+ break;
+ }
+ assert(ptr < end);
+
+ // Now insert the jump. The jump offset is measured in ticks, and
+ // each instrument definition spans 4 ticks... so we jump to tick
+ // 8*4, although jumping to tick 0 would probably work fine, too.
+ // Note: it's possible that some musics don't loop from the start...
+ // in that case we'll have to figure out how the loop range is specified
+ // and then how to handle it appropriately (if it's specified in
+ // ticks, we are fine; but if it's a byte offset, it'll be nasty).
+ const int jump_offset = 8 * 4;
+ memcpy(ptr, "\xf0\x13\x7d\x30\00", 5); ptr += 5; // maybe_jump
+ memcpy(ptr, "\x00\x00", 2); ptr += 2; // cmd -> 0 means always jump
+ memcpy(ptr, "\x00\x00\x00\x00", 4); ptr += 4; // track -> there is only one track, 0
+ memcpy(ptr, "\x00\x00\x00\x01", 4); ptr += 4; // beat -> for now, 1 (first beat)
+ // Ticks
+ *ptr++ = (byte)((jump_offset >> 12) & 0x0F);
+ *ptr++ = (byte)((jump_offset >> 8) & 0x0F);
+ *ptr++ = (byte)((jump_offset >> 4) & 0x0F);
+ *ptr++ = (byte)(jump_offset & 0x0F);
+ memcpy(ptr, "\x00\xf7", 2); ptr += 2; // sysex end marker
+ }
+ // Finally we reinsert the end of song sysex, just in case
+ memcpy(ptr, "\x00\xff\x2f\x00\x00", 5); ptr += 5;
+
+ src_ptr+=size;
+ size = 0;
+
+ return 1;
+}
+
int Scumm::readSoundResourceSmallHeader(int type, int idx) {
- uint32 pos, total_size, size, dw, tag;
- uint32 best_size = 0, best_offs = 0;
+ uint32 pos, total_size, size, tag;
+ uint32 ad_size = 0, ad_offs = 0;
+ uint32 wa_size = 0, wa_offs = 0;
debug(4, "readSoundResourceSmallHeader(%s,%d)", resTypeFromId(type), idx);
//if (_rescache->readResource(roomNr, type, idx))
// return 1;
- total_size = size = _fileHandle.readUint32LE();
- tag = _fileHandle.readUint16LE();
- debug(4, " tag='%c%c', size=%d",
- (char) (tag & 0xff),
- (char) ((tag >> 8) & 0xff), size);
-
- pos = 6;
- while (pos < total_size) {
- size = _fileHandle.readUint32LE();
+ if ((_features & GF_OLD_BUNDLE)) {
+ wa_offs = _fileHandle.pos();
+ wa_size = _fileHandle.readUint16LE();
+ _fileHandle.seek(wa_size - 2, SEEK_CUR);
+ ad_offs = _fileHandle.pos();
+ ad_size = _fileHandle.readUint16LE();
+ _fileHandle.seek(4, SEEK_CUR);
+ total_size = wa_size + ad_size;
+ } else {
+ total_size = size = _fileHandle.readUint32LE();
tag = _fileHandle.readUint16LE();
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;
+ (char) (tag & 0xff),
+ (char) ((tag >> 8) & 0xff), size);
+
+ pos = 6;
+ while (pos < total_size) {
+ size = _fileHandle.readUint32LE();
+ tag = _fileHandle.readUint16LE();
+ 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) && !(ad_offs)) { // AD
+ ad_size = size;
+ ad_offs = _fileHandle.pos();
+ } else if ((tag == 0x4157) && !(wa_offs)) { // WA
+ wa_size = size;
+ wa_offs = _fileHandle.pos();
+ } else { // other AD, WA and nested SO resources
+ if (tag == 0x4F53) { // SO
+ pos -= size;
+ size = 6;
+ pos += 6;
+ }
}
+ _fileHandle.seek(size - 6, SEEK_CUR);
}
- _fileHandle.seek(size - 6, SEEK_CUR);
}
// AD resources have a header, instrument definitions and one MIDI track.
@@ -1063,197 +1165,19 @@ int Scumm::readSoundResourceSmallHeader(int type, int idx) {
// - proper handling of the short (non-music, SFX) AD resources format
// - check the LE/BE handling for platforms other than PC
- if (best_offs != 0) {
- byte *ptr, *track, *instr;
- byte ticks, play_once;
- byte music_type, num_instr;
-
- _fileHandle.seek(best_offs - 6, SEEK_SET);
-
- ptr = createResource(type, idx, best_size);
- _fileHandle.read(ptr, best_size);
-
- music_type = *(ptr + 8); // 0x80: is music; otherwise not.
-
- if (music_type != 0x80) {
- // It's an SFX; we don't know how to handle those yet
- debug(4, "Sound %d not played, format not yet supported", idx);
- nukeResource(type, idx);
- res.roomoffs[type][idx] = 0xFFFFFFFF;
- return 0;
- }
-
- // The "speed" of the song
- ticks = *(ptr + 9);
-
- // Flag that tells us whether we should loop the song (0) or play it only once (1)
- play_once = *(ptr + 10);
-
- // Number of instruments used
- num_instr = *(ptr + 16); // Normally 8
- if (num_instr != 8)
- warning("Sound %d has %d instruments, expected 8", idx, num_instr);
-
- // copy the instrument data in another memory area
- instr = (byte *)calloc(8 * 16, 1);
- assert(instr);
- memcpy(instr, ptr + 0x19, 8*16);
-
- // skip over the rest of the header and copy the MIDI data into a buffer
- size = best_size;
- ptr += 0x19 + 8 * 16;
- size -= 0x19 + 8 * 16;
- 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
-
- // Now nuke the old resource, and replace it with a new one
- nukeResource(type, idx);
- total_size = 8 + 16 + 14 + 8 + 7 + sizeof(OLD256_MIDI_HACK) + size;
- if (!play_once)
- total_size += 24; // Up to 24 additional bytes are needed for the jump sysex
-
- // Write the ADL header (see also above for more information)
- 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;
- memset(ptr, 0, 8); ptr += 8;
- 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;
-
- // We will ignore the PPQN in the original resource, because
- // it's invalid anyway. We use a constant PPQN of 480.
- // memcpy(ptr, &ticks, 2); ptr += 2;
- *ptr++ = 480 >> 8;
- *ptr++ = 480 & 0xFF;
-
- memcpy(ptr, "MTrk", 4); ptr += 4;
- *ptr++ = (byte)(((sizeof(OLD256_MIDI_HACK) + size + 7) >> 24) & 0xFF);
- *ptr++ = (byte)(((sizeof(OLD256_MIDI_HACK) + size + 7) >> 16) & 0xFF);
- *ptr++ = (byte)(((sizeof(OLD256_MIDI_HACK) + size + 7) >> 8) & 0xFF);
- *ptr++ = (byte)(((sizeof(OLD256_MIDI_HACK) + size + 7) ) & 0xFF);
-
- // Conver the ticks into a MIDI tempo.
- dw = (500000 * 256) / ticks;
- debug(4, " ticks = %d, speed = %u", ticks, dw);
-
- // Write a tempo change SysEx
- memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4;
- *ptr++ = (byte)((dw >> 16) & 0xFF);
- *ptr++ = (byte)((dw >> 8) & 0xFF);
- *ptr++ = (byte)(dw & 0xFF);
-
- // Copy our hardcoded instrument table into it
- // Then, convert the instrument table as given in this song resource
- // And write it *over* the hardcoded table.
- // Note: we deliberately.
- memcpy(ptr, OLD256_MIDI_HACK, sizeof(OLD256_MIDI_HACK));
-
-
- /* now fill in the instruments */
- for (int i = 0; i < 8; i++) {
-
- /* flags_1 */
- ptr[95 * i + 30 + 0] = (instr[i * 16 + 3] >> 4) & 0xf;
- ptr[95 * i + 30 + 1] = instr[i * 16 + 3] & 0xf;
-
- /* oplvl_1 */
- ptr[95 * i + 30 + 2] = (instr[i * 16 + 4] >> 4) & 0xf;
- ptr[95 * i + 30 + 3] = instr[i * 16 + 4] & 0xf;
-
- /* atdec_1 */
- ptr[95 * i + 30 + 4] = ((~instr[i * 16 + 5]) >> 4) & 0xf;
- ptr[95 * i + 30 + 5] = (~instr[i * 16 + 5]) & 0xf;
-
- /* sustrel_1 */
- ptr[95 * i + 30 + 6] = ((~instr[i * 16 + 6]) >> 4) & 0xf;
- ptr[95 * i + 30 + 7] = (~instr[i * 16 + 6]) & 0xf;
-
- /* waveform_1 */
- ptr[95 * i + 30 + 8] = (instr[i * 16 + 7] >> 4) & 0xf;
- ptr[95 * i + 30 + 9] = instr[i * 16 + 7] & 0xf;
-
- /* flags_2 */
- ptr[95 * i + 30 + 10] = (instr[i * 16 + 8] >> 4) & 0xf;
- ptr[95 * i + 30 + 11] = instr[i * 16 + 8] & 0xf;
-
- /* oplvl_2 */
- ptr[95 * i + 30 + 12] = 3;
- ptr[95 * i + 30 + 13] = 0xF;
-
- /* atdec_2 */
- ptr[95 * i + 30 + 14] = ((~instr[i * 16 + 10]) >> 4) & 0xf;
- ptr[95 * i + 30 + 15] = (~instr[i * 16 + 10]) & 0xf;
-
- /* sustrel_2 */
- ptr[95 * i + 30 + 16] = ((~instr[i * 16 + 11]) >> 4) & 0xf;
- ptr[95 * i + 30 + 17] = (~instr[i * 16 + 11]) & 0xf;
-
- /* waveform_2 */
- ptr[95 * i + 30 + 18] = (instr[i * 16 + 12] >> 4) & 0xf;
- ptr[95 * i + 30 + 19] = instr[i * 16 + 12] & 0xf;
-
- /* feedback */
- ptr[95 * i + 30 + 20] = (instr[i * 16 + 2] >> 4) & 0xf;
- ptr[95 * i + 30 + 21] = instr[i * 16 + 2] & 0xf;
- }
-
- free(instr);
- ptr += sizeof(OLD256_MIDI_HACK);
-
- // Now copy the actual music data
- memcpy(ptr, track, size);
- free(track);
-
- if (!play_once) {
- // The song is meant to be looped. We achieve this by inserting just
- // before the song end a jump to the song start. More precisely we abuse
- // a S&M sysex, "maybe_jump" to achieve this effect. We could also
- // use a set_loop sysex, but it's a bit longer, a little more complicated,
- // and has no advantage either.
-
- // First, find the track end
- byte *end = ptr + size;
- for (; ptr < end; ptr++) {
- if (*ptr == 0xff && *(ptr + 1) == 0x2f)
- break;
- }
- assert(ptr < end);
-
- // Now insert the jump. The jump offset is measured in ticks, and
- // each instrument definition spans 4 ticks... so we jump to tick
- // 8*4, although jumping to tick 0 would probably work fine, too.
- // Note: it's possible that some musics don't loop from the start...
- // in that case we'll have to figure out how the loop range is specified
- // and then how to handle it appropriately (if it's specified in
- // ticks, we are fine; but if it's a byte offset, it'll be nasty).
- const int jump_offset = 8 * 4;
- memcpy(ptr, "\xf0\x13\x7d\x30\00", 5); ptr += 5; // maybe_jump
- memcpy(ptr, "\x00\x00", 2); ptr += 2; // cmd -> 0 means always jump
- memcpy(ptr, "\x00\x00\x00\x00", 4); ptr += 4; // track -> there is only one track, 0
- memcpy(ptr, "\x00\x00\x00\x01", 4); ptr += 4; // beat -> for now, 1 (first beat)
- // Ticks
- *ptr++ = (byte)((jump_offset >> 12) & 0x0F);
- *ptr++ = (byte)((jump_offset >> 8) & 0x0F);
- *ptr++ = (byte)((jump_offset >> 4) & 0x0F);
- *ptr++ = (byte)(jump_offset & 0x0F);
- memcpy(ptr, "\x00\xf7", 2); ptr += 2; // sysex end marker
-
- // Finally we reinsert the end of song sysex, just in case
- memcpy(ptr, "\x00\xff\x2f\x00\x00", 5); ptr += 5;
- }
-
- return 1;
+ if (ad_offs != 0) {
+ byte *ptr;
+ if (_features & GF_OLD_BUNDLE) {
+ ptr = (byte *) calloc(ad_size - 4, 1);
+ _fileHandle.seek(ad_offs + 4, SEEK_SET);
+ _fileHandle.read(ptr, ad_size - 4);
+ return convertADResource(type, idx, ptr, ad_size - 4);
+ } else {
+ ptr = (byte *) calloc(ad_size - 6, 1);
+ _fileHandle.seek(ad_offs, SEEK_SET);
+ _fileHandle.read(ptr, ad_size - 6);
+ return convertADResource(type, idx, ptr, ad_size - 6);
+ }
}
res.roomoffs[type][idx] = 0xFFFFFFFF;
return 0;
diff --git a/scumm/scumm.h b/scumm/scumm.h
index d4b7c6d2c5..3698794e12 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -642,6 +642,8 @@ public:
protected:
int readSoundResource(int type, int index);
+ int convert_extraflags(byte *ptr, byte * src_ptr);
+ int convertADResource(int type, int index, byte *ptr, int size);
int readSoundResourceSmallHeader(int type, int index);
void setResourceCounter(int type, int index, byte flag);
bool validateResource(const char *str, int type, int index) const;
diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp
index ff641ee67c..3921705c8f 100644
--- a/scumm/scummvm.cpp
+++ b/scumm/scummvm.cpp
@@ -616,8 +616,12 @@ Scumm::Scumm (GameDetector *detector, OSystem *syst)
_imuseDigital = new IMuseDigital(this);
_imuse = NULL;
_playerV2 = NULL;
+ } else if ((_features & GF_AMIGA) && (_features & GF_OLD_BUNDLE)) {
+ _playerV2 = NULL;
+ _imuse = NULL;
+ _imuseDigital = NULL;
} else if (_features & GF_OLD_BUNDLE) {
- if ((_features & GF_AMIGA) || ((_version == 1) && (_gameId == GID_MANIAC)))
+ if ((_version == 1) && (_gameId == GID_MANIAC))
_playerV2 = NULL;
else
_playerV2 = new Player_V2(this);
diff --git a/scumm/sound.cpp b/scumm/sound.cpp
index 48c14640ee..bd88ed261e 100644
--- a/scumm/sound.cpp
+++ b/scumm/sound.cpp
@@ -323,7 +323,7 @@ void Sound::playSound(int soundID) {
memcpy(sound, ptr + 33, size);
_scumm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID);
return;
- } else if (_scumm->_features & GF_OLD256) {
+ } else if (_scumm->_features & GF_FMTOWNS) {
size = READ_LE_UINT32(ptr);
#if 0
// FIXME - this is just some debug output for Zak256