Esempio n. 1
0
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();
	}
}
Esempio n. 2
0
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();
}