cvs server: Diffing . cvs server: Diffing backends cvs server: Diffing backends/PalmOS cvs server: Diffing backends/PalmOS/Rsc cvs server: Diffing backends/PalmOS/Rsc/Resource.Frk cvs server: Diffing backends/PalmOS/Src cvs server: Diffing backends/PalmOS/Src/midi cvs server: Diffing backends/PalmOS/Src/missing cvs server: Diffing backends/PalmOS/Src/missing/sys cvs server: Diffing backends/dc cvs server: Diffing backends/fs cvs server: Diffing backends/fs/morphos cvs server: Diffing backends/fs/palmos cvs server: Diffing backends/fs/posix cvs server: Diffing backends/fs/windows cvs server: Diffing backends/gp32 cvs server: Diffing backends/midi Index: backends/midi/adlib.cpp =================================================================== RCS file: /cvsroot/scummvm/scummvm/backends/midi/adlib.cpp,v retrieving revision 1.36 diff -u -r1.36 adlib.cpp --- backends/midi/adlib.cpp 15 Jul 2003 02:16:32 -0000 1.36 +++ backends/midi/adlib.cpp 20 Jul 2003 16:56:50 -0000 @@ -25,6 +25,8 @@ #include "common/engine.h" // for warning/error/debug #include "common/util.h" +static int tick; + class MidiDriver_ADLIB; struct AdlibVoice; @@ -33,22 +35,22 @@ }; struct AdlibInstrument { - byte flags_1; + byte flags_1; //0 byte oplvl_1; byte atdec_1; byte sustrel_1; byte waveform_1; - byte flags_2; + byte flags_2; //5 byte oplvl_2; byte atdec_2; byte sustrel_2; byte waveform_2; byte feedback; - byte flags_a; + byte flags_a; //11 InstrumentExtra extra_a; - byte flags_b; + byte flags_b; //20 InstrumentExtra extra_b; - byte duration; + byte duration; //29 AdlibInstrument() { memset(this, 0, sizeof(AdlibInstrument)); } }; @@ -152,16 +154,16 @@ }; struct Struct10 { - byte active; - int16 cur_val; - int16 count; - uint16 param; - int16 start_value; - byte loop; - byte table_a[4]; - byte table_b[4]; - int8 unk3; - int8 modwheel; + byte active; //0 + int16 cur_val; //1 + int16 count; //3 + uint16 max_value; //5 + int16 start_value; //7 + byte loop; //9 + byte table_a[4];//10 + byte table_b[4];//14 + int8 unk3; //18 + int8 modwheel; //19 int8 modwheel_last; uint16 speed_lo_max; uint16 num_steps; @@ -236,7 +238,7 @@ 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, @@ -985,6 +987,7 @@ } void MidiDriver_ADLIB::adlib_write(byte port, byte value) { + debug(5, "%8x: adlib_write[%2x] = %2x", tick, port, value); if (_adlib_reg_cache[port] == value) return; _adlib_reg_cache[port] = value; @@ -1003,6 +1006,7 @@ _next_tick -= step; if (!_next_tick) { + tick++; if (_timer_proc) (*_timer_proc)(_timer_param); on_timer(); @@ -1209,7 +1213,7 @@ 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); @@ -1396,7 +1400,7 @@ 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); @@ -1407,7 +1411,10 @@ 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); @@ -1433,7 +1440,7 @@ 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; cvs server: Diffing backends/morphos cvs server: Diffing backends/null cvs server: Diffing backends/sdl cvs server: Diffing backends/wince cvs server: Diffing backends/wince/icons cvs server: Diffing backends/wince/missing cvs server: Diffing backends/wince/missing/sys cvs server: Diffing backends/wince/scumm cvs server: Diffing backends/wince/scummvm cvs server: Diffing backends/wince/simon cvs server: Diffing backends/wince/sky cvs server: Diffing backends/x11 cvs server: Diffing common cvs server: Diffing dists cvs server: Diffing dists/debian cvs server: Diffing dists/redhat cvs server: Diffing gui cvs server: Diffing scumm Index: scumm/resource.cpp =================================================================== RCS file: /cvsroot/scummvm/scummvm/scumm/resource.cpp,v retrieving revision 1.111 diff -u -r1.111 resource.cpp --- scumm/resource.cpp 19 Jul 2003 18:18:01 -0000 1.111 +++ scumm/resource.cpp 20 Jul 2003 16:56:50 -0000 @@ -643,8 +643,12 @@ _fileHandle.seek(fileOffs + _fileOffset, SEEK_SET); if (_features & GF_OLD_BUNDLE) { - size = _fileHandle.readUint16LE(); - _fileHandle.seek(-2, SEEK_CUR); + if ((_version == 3) && !(_features & GF_AMIGA) && (type == rtSound)) { + return readSoundResourceSmallHeader(type, idx); + } else { + size = _fileHandle.readUint16LE(); + _fileHandle.seek(-2, SEEK_CUR); + } } else if (_features & GF_SMALL_HEADER) { if (!(_features & GF_SMALL_NAMES)) _fileHandle.seek(8, SEEK_CUR); @@ -893,6 +897,23 @@ } // FIXME: some default MIDI instruments for INDY3/MI1 +static char ADLIB_INSTR_MIDI_HACK[] = + "\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 + + static char OLD256_MIDI_HACK[] = // 0 "\x00\xf0\x14\x7d\x00" // sysex 00: part on/off @@ -1014,44 +1035,440 @@ "\x06\x02\x00\x00\x04\x00\x03\x02" "\x04\x00\x00\xf7" "\x00\xb7\x07\x64"; // Controller 7 = 100 + +static const byte map_param[7] = { + 0, 2, 3, 4, 8, 9, 15, +}; +static const byte freq2note[128] = { + 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 +}; + +int Scumm::convert_extraflags(byte * ptr, byte * src_ptr) { + int flags = src_ptr[0]; + + int t1, t2, t3, t4, time; + int v1, v2, v3; + + if (!(flags & 0x80)) + return -1; + + t1 = (src_ptr[1] & 0xf0) >> 3; + t2 = (src_ptr[2] & 0xf0) >> 3; + t3 = (src_ptr[3] & 0xf0) >> 3 | (flags & 0x40 ? 8 : 0); + t4 = (src_ptr[3] & 0x0f) << 1; + v1 = (src_ptr[1] & 0x0f) * 2 + 31; + v2 = (src_ptr[2] & 0x0f) * 2 + 31; + v3 = 31; + + /* flags a */ + ptr[0] = 8; + ptr[1] = map_param[flags & 0x7]; + + /* extra a */ + ptr[2] = 0; + ptr[3] = 0; + ptr[4] = t1 >> 4; + ptr[5] = t1 & 0xf; + ptr[6] = v1 >> 4; + ptr[7] = v1 & 0xf; + ptr[8] = t2 >> 4; + ptr[9] = t2 & 0xf; + ptr[10] = v2 >> 4; + ptr[11] = v2 & 0xf; + ptr[12] = t3 >> 4; + ptr[13] = t3 & 0xf; + ptr[14] = t4 >> 4; + ptr[15] = t4 & 0xf; + ptr[16] = v3 >> 4; + ptr[17] = v3 & 0xf; + + time = t1+t2+t3+t4; + if (flags & 0x20) { + int playtime = ((src_ptr[4] >> 4) & 0xf) * 118 + + (src_ptr[4] & 0xf) * 8; + if (playtime > time) + time = playtime; + } + time = ((src_ptr[4] >> 4) & 0xf) * 118 + + (src_ptr[4] & 0xf) * 8; + return time; +} + +int Scumm::convertADResource(int type, int idx, byte * src_ptr, int size) { + + byte * ptr; + byte current_instr[14]; + byte ticks, play_once; + byte music_type, num_instr; + byte *instr, *track; + int delay, delay2; + + int total_size = 8 + 16 + 14 + 8 + 7 + sizeof(OLD256_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; + + src_ptr += 2; + size -= 2; + while (size > 0) { + music_type = *(src_ptr); // 0x80: is music; otherwise not. + switch (music_type) { + case 1: + /* Instrument definition */ + memcpy(current_instr, src_ptr+1, 14); + src_ptr += 15; + size -= 15; + break; + case 2: + /* tone/parammodulation */ + memcpy(ptr, ADLIB_INSTR_MIDI_HACK, + sizeof(ADLIB_INSTR_MIDI_HACK)); + + /* flags_1 */ + ptr[30 + 0] = (current_instr[3] >> 4) & 0xf; + ptr[30 + 1] = current_instr[3] & 0xf; + + /* oplvl_1 */ + ptr[30 + 2] = (current_instr[4] >> 4) & 0xf; + ptr[30 + 3] = current_instr[4] & 0xf; + + /* atdec_1 */ + ptr[30 + 4] = ((~current_instr[5]) >> 4) & 0xf; + ptr[30 + 5] = (~current_instr[5]) & 0xf; + + /* sustrel_1 */ + ptr[30 + 6] = ((~current_instr[6]) >> 4) & 0xf; + ptr[30 + 7] = (~current_instr[6]) & 0xf; + + /* waveform_1 */ + ptr[30 + 8] = (current_instr[7] >> 4) & 0xf; + ptr[30 + 9] = current_instr[7] & 0xf; + + /* flags_2 */ + ptr[30 + 10] = (current_instr[8] >> 4) & 0xf; + ptr[30 + 11] = current_instr[8] & 0xf; + + /* oplvl_2 */ + ptr[30 + 12] = ((current_instr[9]) >> 4) & 0xf; + ptr[30 + 13] = (current_instr[9]) & 0xf; + + /* atdec_2 */ + ptr[30 + 14] = ((~current_instr[10]) >> 4) & 0xf; + ptr[30 + 15] = (~current_instr[10]) & 0xf; + + /* sustrel_2 */ + ptr[30 + 16] = ((~current_instr[11]) >> 4) & 0xf; + ptr[30 + 17] = (~current_instr[11]) & 0xf; + + /* waveform_2 */ + ptr[30 + 18] = (current_instr[12] >> 4) & 0xf; + ptr[30 + 19] = current_instr[12] & 0xf; + + /* feedback */ + ptr[30 + 20] = (current_instr[2] >> 4) & 0xf; + ptr[30 + 21] = current_instr[2] & 0xf; + + { + delay = convert_extraflags(ptr + 30 + 22, src_ptr + 1); + delay2 = convert_extraflags(ptr + 30 + 40, src_ptr + 6); + warning ("delays: %d, %d", delay, delay2); + if (delay2 >= 0 && delay2 < delay) + delay = delay2; + if (delay == -1) + delay = 0; + } + + /* duration */ + ptr[30 + 56] = ((delay * 17 / 63) >> 4) & 0xf; + ptr[30 + 57] = (delay * 17 / 63) & 0xf; + + ptr += sizeof(ADLIB_INSTR_MIDI_HACK); + + { + int freq = ((current_instr[1] & 3) << 10) + | current_instr[0]; + freq <<= ((current_instr[1] >> 2) & 7) + 1; + int note = -12; + while (freq >= 0x100) { + note += 12; + freq >>= 1; + } + if (freq < 0x80) + note = 0; + else + note += freq2note[freq - 0x80]; + + if (note < 0) + note = 0; + else if (note > 127) + note = 127; + + // Insert a note on event + *ptr++ = 0x90; // key on channel 0 + *ptr++ = note; + *ptr++ = 63; + + if (delay > 0) { + while (delay > 0x7f) { + *ptr++ = (delay & 0x7f) | 0x80; + delay >>= 7; + } + *ptr++ = delay; + *ptr++ = 0x80; // key off channel 0; + *ptr++ = note; + *ptr++ = 0; + } + } + + src_ptr += 11; + size -= 11; + break; + + case 0xff: + // Finally we reinsert the end of song sysex, just in case + memcpy(ptr, "\x00\xff\x2f\x00\x00", 5); ptr += 5; + src_ptr++; + size = 0; + break; + + case 0x80: + + // The "speed" of the song + ticks = *(src_ptr + 1); + + // Conver the ticks into a MIDI tempo. + dw = (500000 * 256) / ticks; + debug(4, " ticks = %d, speed = %ld", ticks, dw); + + + // 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 + 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, src_ptr + 0x11, 8*16); + + // 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 = (byte *)calloc(size, 1); + if (track == NULL) { + error("Out of memory while allocating %d", size); + } + memcpy(track, src_ptr, size); // saving MIDI track data + + // 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] = (instr[i * 16 + 9] >> 4) & 0xf; + ptr[95 * i + 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; + + /* 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); + ptr += 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; + 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; + break; + + default: + size = 0; + } + } + //hexdump(getResourceAddress(type, idx), total_size); + 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. @@ -1066,197 +1483,19 @@ // - 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; Index: scumm/script_v2.cpp =================================================================== RCS file: /cvsroot/scummvm/scummvm/scumm/script_v2.cpp,v retrieving revision 2.157 diff -u -r2.157 script_v2.cpp --- scumm/script_v2.cpp 19 Jul 2003 16:10:15 -0000 2.157 +++ scumm/script_v2.cpp 20 Jul 2003 16:56:50 -0000 @@ -549,6 +549,8 @@ else _scummVars[bit_var] &= ~(1 << bit_offset); + debug(4, "setBitVar(%d) = %d", bit_var*16 + bit_offset, + (_scummVars[bit_var] & (1 << bit_offset)) ? 1 : 0); } void Scumm_v2::o2_getBitVar() { @@ -560,6 +562,8 @@ int bit_offset = bit_var & 0x0f; bit_var >>= 4; + debug(4, "getBitVar(%d) = %d", bit_var*16 + bit_offset, + (_scummVars[bit_var] & (1 << bit_offset)) ? 1 : 0); setResult((_scummVars[bit_var] & (1 << bit_offset)) ? 1 : 0); } @@ -1037,6 +1041,8 @@ x = getVarOrDirectByte(0x40) * 8; y = getVarOrDirectByte(0x20) * 2; + + debug(4, "putActor(%d, %d)", x, y); a->putActor(x, y, a->room); } Index: scumm/scumm.h =================================================================== RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v retrieving revision 1.272 diff -u -r1.272 scumm.h --- scumm/scumm.h 20 Jul 2003 00:02:24 -0000 1.272 +++ scumm/scumm.h 20 Jul 2003 16:56:50 -0000 @@ -635,6 +635,8 @@ 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; Index: scumm/scummvm.cpp =================================================================== RCS file: /cvsroot/scummvm/scummvm/scumm/scummvm.cpp,v retrieving revision 2.292 diff -u -r2.292 scummvm.cpp --- scumm/scummvm.cpp 20 Jul 2003 16:02:17 -0000 2.292 +++ scumm/scummvm.cpp 20 Jul 2003 16:56:51 -0000 @@ -615,11 +615,15 @@ _imuseDigital = new IMuseDigital(this); _imuse = NULL; _playerV2 = NULL; - } else if (_features & GF_OLD_BUNDLE) { + } else if (_version <= 2) { if ((_features & GF_AMIGA) || ((_version == 1) && (_gameId == GID_MANIAC))) _playerV2 = NULL; else _playerV2 = new Player_V2(this); + _imuse = NULL; + _imuseDigital = NULL; + } else if ((_features & GF_AMIGA) && (_features & GF_OLD_BUNDLE)) { + _playerV2 = NULL; _imuse = NULL; _imuseDigital = NULL; } else { Index: scumm/sound.cpp =================================================================== RCS file: /cvsroot/scummvm/scummvm/scumm/sound.cpp,v retrieving revision 1.181 diff -u -r1.181 sound.cpp --- scumm/sound.cpp 19 Jul 2003 16:07:33 -0000 1.181 +++ scumm/sound.cpp 20 Jul 2003 16:56:51 -0000 @@ -323,7 +323,7 @@ memcpy(sound, ptr + 33, size); _scumm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID); return; - } else if (_scumm->_features & GF_OLD256) { + } else if (_scumm->_gameId == GID_ZAK256) { size = READ_LE_UINT32(ptr); #if 0 // FIXME - this is just some debug output for Zak256 @@ -515,7 +515,7 @@ return; } - if (_scumm->_features & GF_OLD_BUNDLE) { + if (_scumm->_version <= 2) { //TODO: support maniac v1 sounds if ((_scumm->_version == 1) && (_scumm->_gameId == GID_MANIAC)) return; @@ -529,6 +529,11 @@ if (_scumm->_playerV2) _scumm->_playerV2->startSound (soundID, ptr); } + return; + } + + if (_scumm->_features & GF_OLD_BUNDLE && _scumm->_features & GF_AMIGA) { + // TODO: support amiga sounds return; } cvs server: Diffing scumm/smush cvs server: Diffing simon cvs server: Diffing sky cvs server: Diffing sky/compacts cvs server: Diffing sky/music cvs server: Diffing sound