void Player_V2CMS::stopSound(int nr) { Common::StackLock lock(_mutex); if (_next_nr == nr) { _next_nr = 0; _next_data = 0; } if (_current_nr == nr) { for (int i = 0; i < 4; i++) { clear_channel(i); } _current_nr = 0; _current_data = 0; chainNextSound(); } if (_loadedMidiSong == nr) { _midiData = 0; _midiSongBegin = 0; _midiDelay = 0; offAllChannels(); } }
void Player_V2Base::execute_cmd(ChannelInfo *channel) { uint16 value; int16 offset; uint8 *script_ptr; ChannelInfo * current_channel; ChannelInfo * dest_channel; current_channel = channel; if (channel->d.next_cmd == 0) goto check_stopped; script_ptr = &_current_data[channel->d.next_cmd]; for (;;) { uint8 opcode = *script_ptr++; if (opcode >= 0xf8) { switch (opcode) { case 0xf8: // set hull curve debug(7, "channels[%d]: hull curve %2d", (uint)(channel - _channels), *script_ptr); channel->d.hull_curve = hull_offsets[*script_ptr / 2]; script_ptr++; break; case 0xf9: // set freqmod curve debug(7, "channels[%d]: freqmod curve %2d", (uint)(channel - _channels), *script_ptr); channel->d.freqmod_table = freqmod_offsets[*script_ptr / 4]; channel->d.freqmod_modulo = freqmod_lengths[*script_ptr / 4]; script_ptr++; break; case 0xfd: // clear other channel value = READ_LE_UINT16 (script_ptr) / sizeof (ChannelInfo); debug(7, "clear channel %d", value); script_ptr += 2; // In Indy3, when traveling to Venice a command is // issued to clear channel 4. So we introduce a 4th // channel, which is never used. All OOB accesses are // mapped to this channel. // // The original game had room for 8 channels, but only // channels 0-3 are read, changes to other channels // had no effect. if (value >= ARRAYSIZE (_channels)) value = 4; channel = &_channels[value]; // fall through case 0xfa: // clear current channel if (opcode == 0xfa) debug(7, "clear channel"); channel->d.next_cmd = 0; channel->d.base_freq = 0; channel->d.freq_delta = 0; channel->d.freq = 0; channel->d.volume = 0; channel->d.volume_delta = 0; channel->d.inter_note_pause = 0; channel->d.transpose = 0; channel->d.hull_curve = 0; channel->d.hull_offset = 0; channel->d.hull_counter = 0; channel->d.freqmod_table = 0; channel->d.freqmod_offset = 0; channel->d.freqmod_incr = 0; channel->d.freqmod_multiplier = 0; channel->d.freqmod_modulo = 0; break; case 0xfb: // ret from subroutine debug(7, "ret from sub"); script_ptr = _retaddr; break; case 0xfc: // call subroutine offset = READ_LE_UINT16 (script_ptr); debug(7, "subroutine %d", offset); script_ptr += 2; _retaddr = script_ptr; script_ptr = _current_data + offset; break; case 0xfe: // loop music opcode = *script_ptr++; offset = READ_LE_UINT16 (script_ptr); script_ptr += 2; debug(7, "loop if %d to %d", opcode, offset); if (!channel->array[opcode / 2] || --channel->array[opcode/2]) script_ptr += offset; break; case 0xff: // set parameter opcode = *script_ptr++; value = READ_LE_UINT16 (script_ptr); channel->array[opcode / 2] = value; debug(7, "channels[%d]: set param %2d = %5d", (uint)(channel - _channels), opcode, value); script_ptr += 2; if (opcode == 14) { /* tempo var */ _ticks_per_music_timer = 125; } if (opcode == 0) goto end; break; } } else { // opcode < 0xf8 for (;;) { int16 note, octave; int is_last_note; dest_channel = &_channels[(opcode >> 5) & 3]; if (!(opcode & 0x80)) { int tempo = channel->d.tempo; if (!tempo) tempo = 1; channel->d.time_left = tempo * note_lengths[opcode & 0x1f]; note = *script_ptr++; is_last_note = note & 0x80; note &= 0x7f; if (note == 0x7f) { debug(8, "channels[%d]: pause %d", (uint)(channel - _channels), channel->d.time_left); goto end; } } else { channel->d.time_left = ((opcode & 7) << 8) | *script_ptr++; if ((opcode & 0x10)) { debug(8, "channels[%d]: pause %d", (uint)(channel - _channels), channel->d.time_left); goto end; } is_last_note = 0; note = (*script_ptr++) & 0x7f; } debug(8, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s", (uint)(dest_channel - channel), script_ptr ? (uint)(script_ptr - _current_data - 2) : 0, note, (signed short) dest_channel->d.transpose, channel->d.time_left, dest_channel->d.hull_curve, dest_channel->d.freqmod_table, dest_channel->d.freqmod_incr,dest_channel->d.freqmod_multiplier, is_last_note ? "last":""); uint16 myfreq; dest_channel->d.time_left = channel->d.time_left; dest_channel->d.note_length = channel->d.time_left - dest_channel->d.inter_note_pause; note += dest_channel->d.transpose; while (note < 0) note += 12; octave = note / 12; note = note % 12; dest_channel->d.hull_offset = 0; dest_channel->d.hull_counter = 1; if (_pcjr && dest_channel == &_channels[3]) { dest_channel->d.hull_curve = 196 + note * 12; myfreq = 384 - 64 * octave; } else { myfreq = _freqs_table[note] >> octave; } dest_channel->d.freq = dest_channel->d.base_freq = myfreq; if (is_last_note) goto end; opcode = *script_ptr++; } } } end: channel = current_channel; if (channel->d.time_left) { channel->d.next_cmd = script_ptr - _current_data; return; } channel->d.next_cmd = 0; check_stopped: int i; for (i = 0; i < 4; i++) { if (_channels[i].d.time_left) return; } _current_nr = 0; _current_data = 0; chainNextSound(); }