Add adlib music improvements for indy3/monkeyega/monkeyvga and cleanups from patch #770862

svn-id: r9480
This commit is contained in:
Travis Howell 2003-08-05 05:21:57 +00:00
parent 1eaf41eda4
commit 8bf012d966
5 changed files with 284 additions and 348 deletions

View file

@ -25,6 +25,8 @@
#include "common/engine.h" // for warning/error/debug
#include "common/util.h"
static int tick;
class MidiDriver_ADLIB;
struct AdlibVoice;
@ -156,7 +158,7 @@ struct Struct10 {
byte active;
int16 cur_val;
int16 count;
uint16 param;
uint16 max_value;
int16 start_value;
byte loop;
byte table_a[4];
@ -237,7 +239,7 @@ const byte param_table_1[16] = {
21, 30, 31, 0
};
const uint16 param_table_2[16] = {
const uint16 maxval_table[16] = {
0x2FF, 0x1F, 0x7, 0x3F,
0x0F, 0x0F, 0x0F, 0x3,
0x3F, 0x0F, 0x0F, 0x0F,
@ -1004,6 +1006,7 @@ void MidiDriver_ADLIB::generate_samples(int16 *data, int len) {
_next_tick -= step;
if (!_next_tick) {
tick++;
if (_timer_proc)
(*_timer_proc)(_timer_param);
on_timer();
@ -1210,7 +1213,7 @@ void MidiDriver_ADLIB::struct10_setup(Struct10 *s10) {
s10->num_steps = s10->speed_lo_max = e;
if (f != 2) {
c = s10->param;
c = s10->max_value;
g = s10->start_value;
t = s10->table_b[f];
d = lookup_volume(c, (t & 0x7F) - 31);
@ -1397,7 +1400,7 @@ void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdlibInstrument *instr, byt
port = channel_mappings[chan];
adlib_write(port + 0x20, instr->flags_1);
if (!_game_SmallHeader ||(instr->feedback & 1))
if (!_game_SmallHeader)
adlib_write(port + 0x40, (instr->oplvl_1 | 0x3F) - vol_1 );
else
adlib_write(port + 0x40, instr->oplvl_1);
@ -1408,7 +1411,10 @@ void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdlibInstrument *instr, byt
port = channel_mappings_2[chan];
adlib_write(port + 0x20, instr->flags_2);
adlib_write(port + 0x40, (instr->oplvl_2 | 0x3F) - vol_2 );
if (!_game_SmallHeader)
adlib_write(port + 0x40, (instr->oplvl_1 | 0x3F) - vol_1 );
else
adlib_write(port + 0x40, instr->oplvl_2 );
adlib_write(port + 0x60, 0xff & (~instr->atdec_2));
adlib_write(port + 0x80, 0xff & (~instr->sustrel_2));
adlib_write(port + 0xE0, instr->waveform_2);
@ -1434,7 +1440,7 @@ void MidiDriver_ADLIB::mc_init_stuff (AdlibVoice *voice, Struct10 * s10,
s10->loop = flags & 0x20;
s11->flag0x10 = flags & 0x10;
s11->param = param_table_1[flags & 0xF];
s10->param = param_table_2[flags & 0xF];
s10->max_value = maxval_table[flags & 0xF];
s10->unk3 = 31;
if (s11->flag0x40) {
s10->modwheel = part->_modwheel >> 2;

View file

@ -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,192 +888,36 @@ 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::readSoundResourceSmallHeader(int type, int idx) {
uint32 pos, total_size, size, dw, tag;
uint32 best_size = 0, best_offs = 0;
int Scumm::convertADResource(int type, int idx, byte * src_ptr, int size) {
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();
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;
}
}
_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 bytes MIDI tempo sysex
// + some default instruments
// TODO: - make some real MIDI instrument definitions
// - 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 * ptr;
byte ticks, play_once;
byte music_type, num_instr;
byte *channel, *instr, *track;
int i, ch;
_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.
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);
@ -1084,47 +927,37 @@ int Scumm::readSoundResourceSmallHeader(int type, int idx) {
}
// The "speed" of the song
ticks = *(ptr + 9);
ticks = *(src_ptr + 1);
// Flag that tells us whether we should loop the song (0) or play it only once (1)
play_once = *(ptr + 10);
play_once = *(src_ptr + 2);
// 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);
num_instr = *(src_ptr + 8); // Normally 8
// copy the instrument data in another memory area
instr = (byte *)calloc(8 * 16, 1);
assert(instr);
memcpy(instr, ptr + 0x19, 8*16);
// 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
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
src_ptr += 0x11 + 8 * 16;
size -= 0x11 + 8 * 16;
// 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)
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
// 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);
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;
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;
@ -1138,14 +971,12 @@ int Scumm::readSoundResourceSmallHeader(int type, int idx) {
*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);
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 = %u", ticks, dw);
debug(4, " ticks = %d, speed = %ld", ticks, dw);
// Write a tempo change SysEx
memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4;
@ -1157,63 +988,72 @@ int Scumm::readSoundResourceSmallHeader(int type, int idx) {
// 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++) {
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[95 * i + 30 + 0] = (instr[i * 16 + 3] >> 4) & 0xf;
ptr[95 * i + 30 + 1] = instr[i * 16 + 3] & 0xf;
ptr[30 + 0] = (instr[i * 16 + 3] >> 4) & 0xf;
ptr[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;
ptr[30 + 2] = (instr[i * 16 + 4] >> 4) & 0xf;
ptr[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;
ptr[30 + 4] = ((~instr[i * 16 + 5]) >> 4) & 0xf;
ptr[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;
ptr[30 + 6] = ((~instr[i * 16 + 6]) >> 4) & 0xf;
ptr[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;
ptr[30 + 8] = (instr[i * 16 + 7] >> 4) & 0xf;
ptr[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;
ptr[30 + 10] = (instr[i * 16 + 8] >> 4) & 0xf;
ptr[30 + 11] = instr[i * 16 + 8] & 0xf;
/* oplvl_2 */
ptr[95 * i + 30 + 12] = 3;
ptr[95 * i + 30 + 13] = 0xF;
ptr[30 + 12] = (instr[i * 16 + 9] >> 4) & 0xf;
ptr[30 + 13] = instr[i * 16 + 9] & 0xf;
/* atdec_2 */
ptr[95 * i + 30 + 14] = ((~instr[i * 16 + 10]) >> 4) & 0xf;
ptr[95 * i + 30 + 15] = (~instr[i * 16 + 10]) & 0xf;
ptr[30 + 14] = ((~instr[i * 16 + 10]) >> 4) & 0xf;
ptr[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;
ptr[30 + 16] = ((~instr[i * 16 + 11]) >> 4) & 0xf;
ptr[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;
ptr[30 + 18] = (instr[i * 16 + 12] >> 4) & 0xf;
ptr[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;
ptr[30 + 20] = (instr[i * 16 + 2] >> 4) & 0xf;
ptr[30 + 21] = instr[i * 16 + 2] & 0xf;
ptr += sizeof(ADLIB_INSTR_MIDI_HACK);
}
free(instr);
ptr += sizeof(OLD256_MIDI_HACK);
*ptr++ = 0; // delay 0;
// Now copy the actual music data
memcpy(ptr, track, size);
free(track);
ptr += size;
if (!play_once) {
// The song is meant to be looped. We achieve this by inserting just
@ -1223,7 +1063,8 @@ int Scumm::readSoundResourceSmallHeader(int type, int idx) {
// and has no advantage either.
// First, find the track end
byte *end = ptr + size;
byte *end = ptr;
ptr -= size;
for (; ptr < end; ptr++) {
if (*ptr == 0xff && *(ptr + 1) == 0x2f)
break;
@ -1248,13 +1089,96 @@ int Scumm::readSoundResourceSmallHeader(int type, int idx) {
*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, 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;
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 = 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);
}
}
// 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 bytes MIDI tempo sysex
// + some default instruments
// TODO: - make some real MIDI instrument definitions
// - proper handling of the short (non-music, SFX) AD resources format
// - check the LE/BE handling for platforms other than PC
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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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