Example #1
0
int main(int argc, char** argv) {
	resource_mgr_t *resmgr;
	sfx_state_t sound;
	int res_version = SCI_VERSION_AUTODETECT;
	int sound_nr;
	song_handle_t dummy1;
	int dummy2;
	int arg;
	int it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
	song_iterator_t *base, *ff;

	printf("FreeSCI %s music player Copyright (C) 1999-2007\n", VERSION);
	printf(" Dmitry Jemerov, Christopher T. Lansdown, Sergey Lapin, Rickard Lind,\n"
	       " Carl Muckenhoupt, Christoph Reichenbach, Magnus Reftel, Lars Skovlund,\n"
	       " Rink Springer, Petr Vyhnak, Solomon Peachy, Matt Hargett, Alex Angas\n"
	       " Walter van Niftrik, Rainer Canavan, Ruediger Hanke, Hugues Valois\n"
	       "This program is free software. You can copy and/or modify it freely\n"
	       "according to the terms of the GNU general public license, v2.0\n"
	       "or any later version, at your option.\n"
	       "It comes with ABSOLUTELY NO WARRANTY.\n");
	if (argc < 3) {
		fprintf(stderr, "Syntax: %s <resource dir> <sound number> [<sound number> ...]\n", argv[0]);
		return 1;
	}

	if (!(resmgr = scir_new_resource_manager(argv[1], res_version,
	               0, 1024 * 128))) {
		fprintf(stderr, "Could not find any resources; quitting.\n");
		return 2;
	}

	if (resmgr->sci_version >= SCI_VERSION_01)
		it_type = SCI_SONG_ITERATOR_TYPE_SCI1;

	sfx_init(&sound, resmgr, 0);
	sfx_set_volume(&sound, 127);

	arg = 2 - 1;
	while (++arg < argc) {
		sound_nr = atoi(argv[arg]);
		base = ff = build_iterator(resmgr, sound_nr, it_type,
		                           DUMMY_SOUND_HANDLE);
		printf("Playing resource %d...\n", sound_nr);
		if (sfx_add_song(&sound, ff,
		                 0, DUMMY_SOUND_HANDLE, sound_nr)) {
			fprintf(stderr, "Could not start sound resource. Does it exist?\n");
			return 2;
		}
		sfx_song_set_status(&sound, DUMMY_SOUND_HANDLE, SOUND_STATUS_PLAYING);
		while (sfx_poll(&sound, &dummy1, &dummy2) != SI_FINISHED) {};
	}
	sfx_exit(&sound);
	scir_free_resource_manager(resmgr);
	return 0;
}
Example #2
0
reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) {
	uint16 command = argv[0].toUint16();
	reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
	SongHandle handle = FROBNICATE_HANDLE(obj);
	int number = obj.segment ?
	             GET_SEL32V(obj, number) :
	             -1; /* We were not going to use it anyway */

#ifdef DEBUG_SOUND
	if (command != _K_SCI01_SOUND_UPDATE_CUES) {
		int i;

		debugC(2, kDebugLevelSound, "Command 0x%x", command);
		switch (command) {
		case 0:
			debugC(2, kDebugLevelSound, "[MasterVolume]");
			break;
		case 1:
			debugC(2, kDebugLevelSound, "[Mute]");
			break;
		case 2:
			debugC(2, kDebugLevelSound, "[NOP(2)]");
			break;
		case 3:
			debugC(2, kDebugLevelSound, "[GetPolyphony]");
			break;
		case 4:
			debugC(2, kDebugLevelSound, "[Update]");
			break;
		case 5:
			debugC(2, kDebugLevelSound, "[Init]");
			break;
		case 6:
			debugC(2, kDebugLevelSound, "[Dispose]");
			break;
		case 7:
			debugC(2, kDebugLevelSound, "[Play]");
			break;
		case 8:
			debugC(2, kDebugLevelSound, "[Stop]");
			break;
		case 9:
			debugC(2, kDebugLevelSound, "[Suspend]");
			break;
		case 10:
			debugC(2, kDebugLevelSound, "[Fade]");
			break;
		case 11:
			debugC(2, kDebugLevelSound, "[UpdateCues]");
			break;
		case 12:
			debugC(2, kDebugLevelSound, "[MidiSend]");
			break;
		case 13:
			debugC(2, kDebugLevelSound, "[Reverb]");
			break;
		case 14:
			debugC(2, kDebugLevelSound, "[Hold]");
			break;
		default:
			debugC(2, kDebugLevelSound, "[unknown]");
			break;
		}

		debugC(2, kDebugLevelSound, "(");
		for (i = 1; i < argc; i++) {
			debugC(2, kDebugLevelSound, "%04x:%04x", PRINT_REG(argv[i]));
			if (i + 1 < argc)
				debugC(2, kDebugLevelSound, ", ");
		}
		debugC(2, kDebugLevelSound, ")\n");
	}
#endif

	switch (command) {
	case _K_SCI01_SOUND_MASTER_VOLME : {
		int vol = (argc > 1) ? argv[1].toSint16() : -1;

		if (vol != -1)
			s->_sound.sfx_set_volume(vol << 0xf);
		else
			s->r_acc = make_reg(0, s->_sound.sfx_get_volume() >> 0xf);
		break;
	}
	case _K_SCI01_SOUND_MUTE_SOUND : {
		/* if there's a parameter, we're setting it.  Otherwise,
		   we're querying it. */
		/*int param = UPARAM_OR_ALT(1,-1);

		if (param != -1)
			s->acc = s->sound_server->command(s, SOUND_COMMAND_SET_MUTE, 0, param);
		else
		s->acc = s->sound_server->command(s, SOUND_COMMAND_GET_MUTE, 0, 0);*/

		break;
	}
	case _K_SCI01_SOUND_UNUSED : {
		break;
	}
	case _K_SCI01_SOUND_GET_POLYPHONY : {
		s->r_acc = make_reg(0, sfx_get_player_polyphony());
		break;
	}
	case _K_SCI01_SOUND_PLAY_HANDLE : {
		int looping = GET_SEL32V(obj, loop);
		//int vol = GET_SEL32V(obj, vol);
		int pri = GET_SEL32V(obj, pri);
		RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) argv[2].toUint16();		/* Too lazy to look up a default value for this */

		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
			s->_sound.sfx_song_set_loops(handle, looping);
			s->_sound.sfx_song_renice(handle, pri);
			s->_sound._songlib.setSongRestoreBehavior(handle, rb);
		}

		break;
	}
	case _K_SCI01_SOUND_INIT_HANDLE : {
		//int looping = GET_SEL32V(obj, loop);
		//int vol = GET_SEL32V(obj, vol);
		//int pri = GET_SEL32V(obj, pri);

		if (obj.segment && (s->resmgr->testResource(ResourceId(kResourceTypeSound, number)))) {
			debugC(2, kDebugLevelSound, "Initializing song number %d\n", number);
			s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1,
			                                      handle), 0, handle, number);
			PUT_SEL32(obj, nodePtr, obj);
			PUT_SEL32(obj, handle, obj);
		}
		break;
	}
	case _K_SCI01_SOUND_DISPOSE_HANDLE : {
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			s->_sound.sfx_remove_song(handle);
		}
		break;
	}
	case _K_SCI01_SOUND_UPDATE_HANDLE : {
		/* FIXME: Get these from the sound server */
		int signal = 0;
		int min = 0;
		int sec = 0;
		int frame = 0;

		/* FIXME: Update the sound server state with 'vol' */
		int looping = GET_SEL32V(obj, loop);
		//int vol = GET_SEL32V(obj, vol);
		int pri = GET_SEL32V(obj, pri);

		s->_sound.sfx_song_set_loops(handle, looping);
		s->_sound.sfx_song_renice(handle, pri);

		debugC(2, kDebugLevelSound, "[sound01-update-handle] -- CUE %04x:%04x", PRINT_REG(obj));

		PUT_SEL32V(obj, signal, signal);
		PUT_SEL32V(obj, min, min);
		PUT_SEL32V(obj, sec, sec);
		PUT_SEL32V(obj, frame, frame);

		break;
	}
	case _K_SCI01_SOUND_STOP_HANDLE : {
		PUT_SEL32V(obj, signal, -1);
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
		}
		break;
	}
	case _K_SCI01_SOUND_SUSPEND_HANDLE : {
		int state = argv[2].toUint16();
		int setstate = (state) ?
		               SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING;

		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, setstate);
		}
		break;
	}
	case _K_SCI01_SOUND_FADE_HANDLE : {
		/* There are four parameters that control the fade here.
		 * TODO: Figure out the exact semantics */

		/* FIXME: The next couple of lines actually STOP the song right away */
		PUT_SEL32V(obj, signal, -1);
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
		}
		break;
	}
	case _K_SCI01_SOUND_UPDATE_CUES : {
		int signal = 0;
		int min = 0;
		int sec = 0;
		int frame = 0;
		int result = SI_LOOP; /* small hack */
		int cue = 0;

		while (result == SI_LOOP)
			result = s->_sound.sfx_poll_specific(handle, &cue);

		switch (result) {

		case SI_ABSOLUTE_CUE:
			signal = cue;
			debugC(2, kDebugLevelSound, "---    [CUE] %04x:%04x Absolute Cue: %d\n",
			          PRINT_REG(obj), signal);

			PUT_SEL32V(obj, signal, signal);
			break;

		case SI_RELATIVE_CUE:
			signal = cue;
			debugC(2, kDebugLevelSound, "---    [CUE] %04x:%04x Relative Cue: %d\n",
			          PRINT_REG(obj), cue);

			/* FIXME to match commented-out semantics
			 * below, with proper storage of dataInc and
			 * signal in the iterator code. */
			PUT_SEL32V(obj, dataInc, signal);
			PUT_SEL32V(obj, signal, signal);
			break;

		case SI_FINISHED:
			debugC(2, kDebugLevelSound, "---    [FINISHED] %04x:%04x\n", PRINT_REG(obj));
			PUT_SEL32V(obj, signal, 0xffff);
			break;

		case SI_LOOP:
			break; /* Doesn't happen */
		}

		/*		switch (signal) */
		/*		{ */
		/*		case 0x00: */
		/*			if (dataInc!=GET_SEL32V(obj, dataInc)) */
		/*			{ */
		/*				PUT_SEL32V(obj, dataInc, dataInc); */
		/*				PUT_SEL32V(obj, signal, dataInc+0x7f); */
		/*			} else */
		/*			{ */
		/*				PUT_SEL32V(obj, signal, signal); */
		/*			} */
		/*			break; */
		/*		case 0xFF: /\* May be unnecessary *\/ */
		/*			s->_sound.sfx_song_set_status(*/
		/*					    handle, SOUND_STATUS_STOPPED); */
		/*			break; */
		/*		default : */
		/*			if (dataInc!=GET_SEL32V(obj, dataInc)) */
		/*			{ */
		/*				PUT_SEL32V(obj, dataInc, dataInc); */
		/*				PUT_SEL32V(obj, signal, dataInc+0x7f); */
		/*			} else */
		/*			{ */
		/*				PUT_SEL32V(obj, signal, signal); */
		/*			} */
		/*			break; */
		/*		} */

		PUT_SEL32V(obj, min, min);
		PUT_SEL32V(obj, sec, sec);
		PUT_SEL32V(obj, frame, frame);
		break;
	}
	case _K_SCI01_SOUND_MIDI_SEND : {
		int channel = argv[2].toSint16();
		int midiCmd = argv[3].toUint16() == 0xff ?
		              0xe0 : /* Pitch wheel */
		              0xb0; /* argv[3].toUint16() is actually a controller number */
		int controller = argv[3].toUint16();
		int param = argv[4].toUint16();

		s->_sound.sfx_send_midi(handle,
		              channel, midiCmd, controller, param);
		break;
	}
	case _K_SCI01_SOUND_REVERB : {
		break;
	}
	case _K_SCI01_SOUND_HOLD : {
		//int flag = argv[2].toSint16();
		break;
	}
	}

	return s->r_acc;
}
Example #3
0
reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) {
	uint16 command = argv[0].toUint16();
	reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
	SongHandle handle = FROBNICATE_HANDLE(obj);
	int number = obj.segment ?
	             GET_SEL32V(obj, number) :
	             -1; /* We were not going to use it anyway */

#ifdef DEBUG_SOUND
	if (command != _K_SCI1_SOUND_UPDATE_CUES) {
		int i;

		debugC(2, kDebugLevelSound, "Command 0x%x", command);
		switch (command) {
		case 0:
			debugC(2, kDebugLevelSound, "[MasterVolume]");
			break;
		case 1:
			debugC(2, kDebugLevelSound, "[Mute]");
			break;
		case 2:
			debugC(2, kDebugLevelSound, "[NOP(2)]");
			break;
		case 3:
			debugC(2, kDebugLevelSound, "[GetPolyphony]");
			break;
		case 4:
			debugC(2, kDebugLevelSound, "[GetAudioCapability]");
			break;
		case 5:
			debugC(2, kDebugLevelSound, "[GlobalSuspend]");
			break;
		case 6:
			debugC(2, kDebugLevelSound, "[Init]");
			break;
		case 7:
			debugC(2, kDebugLevelSound, "[Dispose]");
			break;
		case 8:
			debugC(2, kDebugLevelSound, "[Play]");
			break;
		case 9:
			debugC(2, kDebugLevelSound, "[Stop]");
			break;
		case 10:
			debugC(2, kDebugLevelSound, "[SuspendHandle]");
			break;
		case 11:
			debugC(2, kDebugLevelSound, "[Fade]");
			break;
		case 12:
			debugC(2, kDebugLevelSound, "[Hold]");
			break;
		case 13:
			debugC(2, kDebugLevelSound, "[Unused(13)]");
			break;
		case 14:
			debugC(2, kDebugLevelSound, "[SetVolume]");
			break;
		case 15:
			debugC(2, kDebugLevelSound, "[SetPriority]");
			break;
		case 16:
			debugC(2, kDebugLevelSound, "[SetLoop]");
			break;
		case 17:
			debugC(2, kDebugLevelSound, "[UpdateCues]");
			break;
		case 18:
			debugC(2, kDebugLevelSound, "[MidiSend]");
			break;
		case 19:
			debugC(2, kDebugLevelSound, "[Reverb]");
			break;
		case 20:
			debugC(2, kDebugLevelSound, "[UpdateVolPri]");
			break;
		default:
			debugC(2, kDebugLevelSound, "[unknown]");
			break;
		}

		debugC(2, kDebugLevelSound, "(");
		for (i = 1; i < argc; i++) {
			debugC(2, kDebugLevelSound, "%04x:%04x", PRINT_REG(argv[i]));
			if (i + 1 < argc)
				debugC(2, kDebugLevelSound, ", ");
		}
		debugC(2, kDebugLevelSound, ")\n");
	}
#endif	// DEBUG_SOUND

	switch (command) {
	case _K_SCI1_SOUND_MASTER_VOLME : {
		/*int vol = UPARAM_OR_ALT (1, -1);

		 if (vol != -1)
		         s->acc = s->sound_server->command(s, SOUND_COMMAND_SET_VOLUME, 0, vol);
		 else
		         s->acc = s->sound_server->command(s, SOUND_COMMAND_GET_VOLUME, 0, 0);
			break;*/
	}
	case _K_SCI1_SOUND_MUTE_SOUND : {
		/* if there's a parameter, we're setting it.  Otherwise,
		   we're querying it. */
		/*int param = UPARAM_OR_ALT(1,-1);

		if (param != -1)
			s->acc = s->sound_server->command(s, SOUND_COMMAND_SET_MUTE, 0, param);
		else
			s->acc = s->sound_server->command(s, SOUND_COMMAND_GET_MUTE, 0, 0);
			break;*/
	}
	case _K_SCI1_SOUND_UNUSED1 : {
		break;
	}
	case _K_SCI1_SOUND_GET_POLYPHONY : {
		/*s->acc = s->sound_server->command(s, SOUND_COMMAND_TEST, 0, 0);*/
		break;
	}
	case _K_SCI1_SOUND_GET_AUDIO_CAPABILITY : {
		// Tests for digital audio support
		return make_reg(0, 1);
	}
	case _K_SCI1_SOUND_PLAY_HANDLE : {
		int looping = GET_SEL32V(obj, loop);
		//int vol = GET_SEL32V(obj, vol);
		int pri = GET_SEL32V(obj, pri);
		int sampleLen = 0;
		Song *song = s->_sound._songlib.findSong(handle);

		if (GET_SEL32V(obj, nodePtr) && (song && number != song->_resourceNum)) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			s->_sound.sfx_remove_song(handle);
			PUT_SEL32(obj, nodePtr, NULL_REG);
		}

		if (!GET_SEL32V(obj, nodePtr) && obj.segment) {
			// In SCI1.1 games, sound effects are started from here. If we can find
			// a relevant audio resource, play it, otherwise switch to synthesized
			// effects. If the resource exists, play it using map 65535 (sound
			// effects map)
			if (s->resmgr->testResource(ResourceId(kResourceTypeAudio, number)) &&
				s->_version >= SCI_VERSION_1_1) {
				// Found a relevant audio resource, play it
				s->_sound.stopAudio();
				warning("Initializing audio resource instead of requested sound resource %d\n", number);
				sampleLen = s->_sound.startAudio(65535, number);
				// Also create iterator, that will fire SI_FINISHED event, when the sound is done playing
				s->_sound.sfx_add_song(build_timeriterator(s, sampleLen), 0, handle, number);
			} else {
				if (!s->resmgr->testResource(ResourceId(kResourceTypeSound, number))) {
					warning("Could not open song number %d", number);
					// Send a "stop handle" event so that the engine won't wait forever here
					s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
					PUT_SEL32V(obj, signal, -1);
					return s->r_acc;
				}
				debugC(2, kDebugLevelSound, "Initializing song number %d\n", number);
				s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1,
				                          handle), 0, handle, number);
			}

			PUT_SEL32(obj, nodePtr, obj);
			PUT_SEL32(obj, handle, obj);
		}

		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
			s->_sound.sfx_song_set_loops(handle, looping);
			s->_sound.sfx_song_renice(handle, pri);
		}

		break;
	}
	case _K_SCI1_SOUND_INIT_HANDLE : {
		//int looping = GET_SEL32V(obj, loop);
		//int vol = GET_SEL32V(obj, vol);
		//int pri = GET_SEL32V(obj, pri);

		if (GET_SEL32V(obj, nodePtr)) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			s->_sound.sfx_remove_song(handle);
		}

		if (obj.segment && (s->resmgr->testResource(ResourceId(kResourceTypeSound, number)))) {
			debugC(2, kDebugLevelSound, "Initializing song number %d\n", number);
			s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1,
			                                    handle), 0, handle, number);
			PUT_SEL32(obj, nodePtr, obj);
			PUT_SEL32(obj, handle, obj);
		}
		break;
	}
	case _K_SCI1_SOUND_DISPOSE_HANDLE : {
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			s->_sound.sfx_remove_song(handle);
		}
		break;
	}
	case _K_SCI1_SOUND_STOP_HANDLE : {
		PUT_SEL32V(obj, signal, -1);
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
		}
		break;
	}
	case _K_SCI1_SOUND_SUSPEND_HANDLE : {
		break;
	}
	case _K_SCI1_SOUND_FADE_HANDLE : {
		fade_params_t fade;
		if (obj.segment) {
			fade.final_volume = argv[2].toUint16();
			fade.ticks_per_step = argv[3].toUint16();
			fade.step_size = argv[4].toUint16();
			fade.action = argv[5].toUint16() ?
			              FADE_ACTION_FADE_AND_STOP :
			              FADE_ACTION_FADE_AND_CONT;

			s->_sound.sfx_song_set_fade(handle,  &fade);

			/* FIXME: The next couple of lines actually STOP the handle, rather
			** than fading it! */
			if (argv[5].toUint16()) {
				PUT_SEL32V(obj, signal, -1);
				PUT_SEL32V(obj, nodePtr, 0);
				PUT_SEL32V(obj, handle, 0);
				s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			} else {
				// FIXME: Support fade-and-continue. For now, send signal right away.
				PUT_SEL32V(obj, signal, -1);
			}
		}
		break;
	}
	case _K_SCI1_SOUND_HOLD_HANDLE : {
		int value = argv[2].toSint16();

		s->_sound.sfx_song_set_hold(handle, value);
		break;
	}
	case _K_SCI1_SOUND_UNUSED2 : {
		break;
	}
	case _K_SCI1_SOUND_SET_HANDLE_VOLUME : {
		break;
	}
	case _K_SCI1_SOUND_SET_HANDLE_PRIORITY : {
		int value = argv[2].toSint16();

		script_set_priority(s, obj, value);
		break;
	}
	case _K_SCI1_SOUND_SET_HANDLE_LOOP : {
		break;
	}
	case _K_SCI1_SOUND_UPDATE_CUES : {
		int signal = 0;
		//int min = 0;
		//int sec = 0;
		//int frame = 0;
		int result = SI_LOOP; /* small hack */
		int cue = 0;

		while (result == SI_LOOP)
			result = s->_sound.sfx_poll_specific(handle, &cue);

		switch (result) {

		case SI_ABSOLUTE_CUE:
			signal = cue;
			debugC(2, kDebugLevelSound, "[CUE] %04x:%04x Absolute Cue: %d\n",
			        PRINT_REG(obj), signal);

			PUT_SEL32V(obj, signal, signal);
			break;

		case SI_RELATIVE_CUE:
			debugC(2, kDebugLevelSound, "[CUE] %04x:%04x Relative Cue: %d\n",
			        PRINT_REG(obj), cue);

			PUT_SEL32V(obj, dataInc, cue);
			PUT_SEL32V(obj, signal, cue + 127);
			break;

		case SI_FINISHED:
			PUT_SEL32V(obj, signal, 0xffff);
			break;

		case SI_LOOP:
			break; /* Doesn't happen */
		}
		break;
	}
	case _K_SCI1_SOUND_MIDI_SEND : {
		s->_sound.sfx_send_midi(handle,
		              argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16(), argv[5].toUint16());
		break;
	}
	case _K_SCI1_SOUND_REVERB : {
		break;
	}
	case _K_SCI1_SOUND_UPDATE_VOL_PRI : {
		break;
	}
	}
	return s->r_acc;
}
Example #4
0
reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
	reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
	uint16 command = argv[0].toUint16();
	SongHandle handle = FROBNICATE_HANDLE(obj);
	int number = obj.segment ?
	             GET_SEL32V(obj, number) :
	             -1; /* We were not going to use it anyway */

#ifdef DEBUG_SOUND
	int i;

	debugC(2, kDebugLevelSound, "Command 0x%x", command);
	switch (command) {
	case 0:
		debugC(2, kDebugLevelSound, "[InitObj]");
		break;
	case 1:
		debugC(2, kDebugLevelSound, "[Play]");
		break;
	case 2:
		debugC(2, kDebugLevelSound, "[NOP]");
		break;
	case 3:
		debugC(2, kDebugLevelSound, "[DisposeHandle]");
		break;
	case 4:
		debugC(2, kDebugLevelSound, "[SetSoundOn(?)]");
		break;
	case 5:
		debugC(2, kDebugLevelSound, "[Stop]");
		break;
	case 6:
		debugC(2, kDebugLevelSound, "[Suspend]");
		break;
	case 7:
		debugC(2, kDebugLevelSound, "[Resume]");
		break;
	case 8:
		debugC(2, kDebugLevelSound, "[Get(Set?)Volume]");
		break;
	case 9:
		debugC(2, kDebugLevelSound, "[Signal: Obj changed]");
		break;
	case 10:
		debugC(2, kDebugLevelSound, "[Fade(?)]");
		break;
	case 11:
		debugC(2, kDebugLevelSound, "[ChkDriver]");
		break;
	case 12:
		debugC(2, kDebugLevelSound, "[PlayNextSong (formerly StopAll)]");
		break;
	default:
		debugC(2, kDebugLevelSound, "[unknown]");
		break;
	}

	debugC(2, kDebugLevelSound, "(");
	for (i = 1; i < argc; i++) {
		debugC(2, kDebugLevelSound, "%04x:%04x", PRINT_REG(argv[i]));
		if (i + 1 < argc)
			debugC(2, kDebugLevelSound, ", ");
	}
	debugC(2, kDebugLevelSound, ")\n");
#endif	// DEBUG_SOUND


	switch (command) {
	case _K_SCI0_SOUND_INIT_HANDLE:
		if (obj.segment) {
			debugC(2, kDebugLevelSound, "Initializing song number %d\n", GET_SEL32V(obj, number));
			s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI0,
			                                               handle), 0, handle, number);

			PUT_SEL32V(obj, state, _K_SOUND_STATUS_INITIALIZED);
			PUT_SEL32(obj, handle, obj); /* ``sound handle'': we use the object address */
		}
		break;

	case _K_SCI0_SOUND_PLAY_HANDLE:
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
			s->_sound.sfx_song_set_loops(handle, GET_SEL32V(obj, loop));
			PUT_SEL32V(obj, state, _K_SOUND_STATUS_PLAYING);
		}
		break;

	case _K_SCI0_SOUND_NOP:
		break;

	case _K_SCI0_SOUND_DISPOSE_HANDLE:
		if (obj.segment) {
			s->_sound.sfx_remove_song(handle);
		}
		PUT_SEL32V(obj, handle, 0x0000);
		break;

	case _K_SCI0_SOUND_STOP_HANDLE:
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			PUT_SEL32V(obj, state, SOUND_STATUS_STOPPED);
		}
		break;

	case _K_SCI0_SOUND_SUSPEND_HANDLE:
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_SUSPENDED);
			PUT_SEL32V(obj, state, SOUND_STATUS_SUSPENDED);
		}
		break;

	case _K_SCI0_SOUND_RESUME_HANDLE:
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
			PUT_SEL32V(obj, state, SOUND_STATUS_PLAYING);
		}
		break;

	case _K_SCI0_SOUND_MUTE_SOUND: {
		/* if there's a parameter, we're setting it.  Otherwise,
		   we're querying it. */
		/*int param = UPARAM_OR_ALT(1,-1);

		if (param != -1)
		s->acc = s->sound_server->command(s, SOUND_COMMAND_SET_MUTE, 0, param);
		else
		s->acc = s->sound_server->command(s, SOUND_COMMAND_GET_MUTE, 0, 0);*/

	}
	break;

	case _K_SCI0_SOUND_VOLUME: {
		/* range from 0x0 to 0xf */
		/* parameter optional. If present, set.*/
		int vol = (argc > 1) ? argv[1].toSint16() : -1;

		if (vol != -1)
			s->_sound.sfx_set_volume(vol << 0xf);
		else
			s->r_acc = make_reg(0, s->_sound.sfx_get_volume() >> 0xf);
	}
	break;

	case _K_SCI0_SOUND_UPDATE_VOL_PRI:
		if (obj.segment) {
			s->_sound.sfx_song_set_loops(handle, GET_SEL32V(obj, loop));
			script_set_priority(s, obj, GET_SEL32V(obj, pri));
		}
		break;

	case _K_SCI0_SOUND_FADE_HANDLE:
		/*s->sound_server->command(s, SOUND_COMMAND_FADE_HANDLE, obj, 120);*/ /* Fade out in 2 secs */
		/* FIXME: The next couple of lines actually STOP the handle, rather
		** than fading it! */
		if (obj.segment) {
			s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
			PUT_SEL32V(obj, state, SOUND_STATUS_STOPPED);
			PUT_SEL32V(obj, signal, -1);
		}
		break;

	case _K_SCI0_SOUND_GET_POLYPHONY:
		s->r_acc = make_reg(0, sfx_get_player_polyphony());
		break;

	case _K_SCI0_SOUND_PLAY_NEXT:
		/* s->_sound.sfx_all_stop();*/
		break;

	default:
		warning("Unhandled DoSound command: %x", command);

	}
	//	process_sound_events(s); /* Take care of incoming events */

	return s->r_acc;
}