mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 03:40:25 +00:00
6b58973536
svn-id: r39289
993 lines
25 KiB
C++
993 lines
25 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "sci/engine/state.h"
|
|
#include "sci/sfx/player.h"
|
|
#include "sci/engine/kernel.h"
|
|
|
|
namespace Sci {
|
|
|
|
#define _K_SCI0_SOUND_INIT_HANDLE 0
|
|
#define _K_SCI0_SOUND_PLAY_HANDLE 1
|
|
#define _K_SCI0_SOUND_NOP 2
|
|
#define _K_SCI0_SOUND_DISPOSE_HANDLE 3
|
|
#define _K_SCI0_SOUND_MUTE_SOUND 4
|
|
#define _K_SCI0_SOUND_STOP_HANDLE 5
|
|
#define _K_SCI0_SOUND_SUSPEND_HANDLE 6
|
|
#define _K_SCI0_SOUND_RESUME_HANDLE 7
|
|
#define _K_SCI0_SOUND_VOLUME 8
|
|
#define _K_SCI0_SOUND_UPDATE_VOL_PRI 9
|
|
#define _K_SCI0_SOUND_FADE_HANDLE 10
|
|
#define _K_SCI0_SOUND_GET_POLYPHONY 11
|
|
#define _K_SCI0_SOUND_PLAY_NEXT 12
|
|
|
|
#define _K_SCI01_SOUND_MASTER_VOLME 0 /* Set/Get */
|
|
#define _K_SCI01_SOUND_MUTE_SOUND 1
|
|
#define _K_SCI01_SOUND_UNUSED 2
|
|
#define _K_SCI01_SOUND_GET_POLYPHONY 3
|
|
#define _K_SCI01_SOUND_UPDATE_HANDLE 4
|
|
#define _K_SCI01_SOUND_INIT_HANDLE 5
|
|
#define _K_SCI01_SOUND_DISPOSE_HANDLE 6
|
|
#define _K_SCI01_SOUND_PLAY_HANDLE 7
|
|
#define _K_SCI01_SOUND_STOP_HANDLE 8
|
|
#define _K_SCI01_SOUND_SUSPEND_HANDLE 9 /* or resume */
|
|
#define _K_SCI01_SOUND_FADE_HANDLE 10
|
|
#define _K_SCI01_SOUND_UPDATE_CUES 11
|
|
#define _K_SCI01_SOUND_MIDI_SEND 12
|
|
#define _K_SCI01_SOUND_REVERB 13 /* Get/Set */
|
|
#define _K_SCI01_SOUND_HOLD 14
|
|
|
|
#define _K_SCI1_SOUND_MASTER_VOLME 0 /* Set/Get */
|
|
#define _K_SCI1_SOUND_MUTE_SOUND 1
|
|
#define _K_SCI1_SOUND_UNUSED1 2
|
|
#define _K_SCI1_SOUND_GET_POLYPHONY 3
|
|
#define _K_SCI1_SOUND_GET_AUDIO_CAPABILITY 4
|
|
#define _K_SCI1_SOUND_SUSPEND_SOUND 5
|
|
#define _K_SCI1_SOUND_INIT_HANDLE 6
|
|
#define _K_SCI1_SOUND_DISPOSE_HANDLE 7
|
|
#define _K_SCI1_SOUND_PLAY_HANDLE 8
|
|
#define _K_SCI1_SOUND_STOP_HANDLE 9
|
|
#define _K_SCI1_SOUND_SUSPEND_HANDLE 10 /* or resume */
|
|
#define _K_SCI1_SOUND_FADE_HANDLE 11
|
|
#define _K_SCI1_SOUND_HOLD_HANDLE 12
|
|
#define _K_SCI1_SOUND_UNUSED2 13
|
|
#define _K_SCI1_SOUND_SET_HANDLE_VOLUME 14
|
|
#define _K_SCI1_SOUND_SET_HANDLE_PRIORITY 15
|
|
#define _K_SCI1_SOUND_SET_HANDLE_LOOP 16
|
|
#define _K_SCI1_SOUND_UPDATE_CUES 17
|
|
#define _K_SCI1_SOUND_MIDI_SEND 18
|
|
#define _K_SCI1_SOUND_REVERB 19 /* Get/Set */
|
|
#define _K_SCI1_SOUND_UPDATE_VOL_PRI 20
|
|
|
|
#define _K_SCI1_AUDIO_POSITION 6 /* Return current position in audio stream */
|
|
|
|
#define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */
|
|
#define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */
|
|
|
|
#define FROBNICATE_HANDLE(reg) ((reg).segment << 16 | (reg).offset)
|
|
#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff))
|
|
#define SCRIPT_ASSERT_ZERO(fun) if (fun) script_debug_flag = script_error_flag = 1;
|
|
|
|
|
|
static void script_set_priority(EngineState *s, reg_t obj, int priority) {
|
|
int song_nr = GET_SEL32V(obj, number);
|
|
Resource *song = s->resmgr->findResource(kResourceTypeSound, song_nr, 0);
|
|
int flags = GET_SEL32V(obj, flags);
|
|
|
|
if (priority == -1) {
|
|
if (song->data[0] == 0xf0)
|
|
priority = song->data[1];
|
|
else
|
|
warning("Attempt to unset song priority when there is no built-in value");
|
|
|
|
flags &= ~SCI1_SOUND_FLAG_SCRIPTED_PRI;
|
|
} else flags |= SCI1_SOUND_FLAG_SCRIPTED_PRI;
|
|
|
|
sfx_song_renice(&s->sound, FROBNICATE_HANDLE(obj), priority);
|
|
PUT_SEL32V(obj, flags, flags);
|
|
}
|
|
|
|
SongIterator *build_iterator(EngineState *s, int song_nr, int type, songit_id_t id) {
|
|
Resource *song = s->resmgr->findResource(kResourceTypeSound, song_nr, 0);
|
|
|
|
if (!song)
|
|
return NULL;
|
|
|
|
return songit_new(song->data, song->size, type, id);
|
|
}
|
|
|
|
|
|
void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */
|
|
int result;
|
|
song_handle_t handle;
|
|
int cue;
|
|
|
|
if (s->version >= SCI_VERSION_FTU_DOSOUND_VARIANT_1)
|
|
return;
|
|
/* SCI01 and later explicitly poll for everything */
|
|
|
|
while ((result = sfx_poll(&s->sound, &handle, &cue))) {
|
|
reg_t obj = DEFROBNICATE_HANDLE(handle);
|
|
if (!is_object(s, obj)) {
|
|
warning("Non-object "PREG" received sound signal (%d/%d)", PRINT_REG(obj), result, cue);
|
|
return;
|
|
}
|
|
|
|
switch (result) {
|
|
|
|
case SI_LOOP:
|
|
SCIkdebug(SCIkSOUND, "[process-sound] Song "PREG" looped (to %d)\n",
|
|
PRINT_REG(obj), cue);
|
|
/* PUT_SEL32V(obj, loops, GET_SEL32V(obj, loop) - 1);*/
|
|
PUT_SEL32V(obj, signal, -1);
|
|
break;
|
|
|
|
case SI_RELATIVE_CUE:
|
|
SCIkdebug(SCIkSOUND, "[process-sound] Song "PREG" received relative cue %d\n",
|
|
PRINT_REG(obj), cue);
|
|
PUT_SEL32V(obj, signal, cue + 0x7f);
|
|
break;
|
|
|
|
case SI_ABSOLUTE_CUE:
|
|
SCIkdebug(SCIkSOUND, "[process-sound] Song "PREG" received absolute cue %d\n",
|
|
PRINT_REG(obj), cue);
|
|
PUT_SEL32V(obj, signal, cue);
|
|
break;
|
|
|
|
case SI_FINISHED:
|
|
SCIkdebug(SCIkSOUND, "[process-sound] Song "PREG" finished\n",
|
|
PRINT_REG(obj));
|
|
PUT_SEL32V(obj, signal, -1);
|
|
PUT_SEL32V(obj, state, _K_SOUND_STATUS_STOPPED);
|
|
break;
|
|
|
|
default:
|
|
sciprintf("Unexpected result from sfx_poll: %d\n", result);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
|
reg_t obj = KP_ALT(1, NULL_REG);
|
|
uint16 command = UKPV(0);
|
|
song_handle_t handle = FROBNICATE_HANDLE(obj);
|
|
int number = obj.segment ?
|
|
GET_SEL32V(obj, number) :
|
|
-1; /* We were not going to use it anyway */
|
|
|
|
if (s->debug_mode & (1 << SCIkSOUNDCHK_NR)) {
|
|
int i;
|
|
|
|
SCIkdebug(SCIkSOUND, "Command 0x%x", command);
|
|
switch (command) {
|
|
case 0:
|
|
sciprintf("[InitObj]");
|
|
break;
|
|
case 1:
|
|
sciprintf("[Play]");
|
|
break;
|
|
case 2:
|
|
sciprintf("[NOP]");
|
|
break;
|
|
case 3:
|
|
sciprintf("[DisposeHandle]");
|
|
break;
|
|
case 4:
|
|
sciprintf("[SetSoundOn(?)]");
|
|
break;
|
|
case 5:
|
|
sciprintf("[Stop]");
|
|
break;
|
|
case 6:
|
|
sciprintf("[Suspend]");
|
|
break;
|
|
case 7:
|
|
sciprintf("[Resume]");
|
|
break;
|
|
case 8:
|
|
sciprintf("[Get(Set?)Volume]");
|
|
break;
|
|
case 9:
|
|
sciprintf("[Signal: Obj changed]");
|
|
break;
|
|
case 10:
|
|
sciprintf("[Fade(?)]");
|
|
break;
|
|
case 11:
|
|
sciprintf("[ChkDriver]");
|
|
break;
|
|
case 12:
|
|
sciprintf("[PlayNextSong (formerly StopAll)]");
|
|
break;
|
|
default:
|
|
sciprintf("[unknown]");
|
|
break;
|
|
}
|
|
|
|
sciprintf("(");
|
|
for (i = 1; i < argc; i++) {
|
|
sciprintf(PREG, PRINT_REG(argv[i]));
|
|
if (i + 1 < argc)
|
|
sciprintf(", ");
|
|
}
|
|
sciprintf(")\n");
|
|
}
|
|
|
|
|
|
switch (command) {
|
|
case _K_SCI0_SOUND_INIT_HANDLE:
|
|
if (obj.segment) {
|
|
sciprintf("Initializing song number %d\n", GET_SEL32V(obj, number));
|
|
SCRIPT_ASSERT_ZERO(sfx_add_song(&s->sound,
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_PLAYING);
|
|
sfx_song_set_loops(&s->sound,
|
|
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) {
|
|
sfx_remove_song(&s->sound, handle);
|
|
}
|
|
PUT_SEL32V(obj, handle, 0x0000);
|
|
break;
|
|
|
|
case _K_SCI0_SOUND_STOP_HANDLE:
|
|
if (obj.segment) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
PUT_SEL32V(obj, state, SOUND_STATUS_STOPPED);
|
|
}
|
|
break;
|
|
|
|
case _K_SCI0_SOUND_SUSPEND_HANDLE:
|
|
if (obj.segment) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_SUSPENDED);
|
|
PUT_SEL32V(obj, state, SOUND_STATUS_SUSPENDED);
|
|
}
|
|
break;
|
|
|
|
case _K_SCI0_SOUND_RESUME_HANDLE:
|
|
if (obj.segment) {
|
|
sfx_song_set_status(&s->sound,
|
|
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 = SKPV_OR_ALT(1, -1);
|
|
|
|
if (vol != -1)
|
|
sfx_set_volume(&s->sound, vol << 0xf);
|
|
else
|
|
s->r_acc = make_reg(0, sfx_get_volume(&s->sound) >> 0xf);
|
|
}
|
|
break;
|
|
|
|
case _K_SCI0_SOUND_UPDATE_VOL_PRI:
|
|
if (obj.segment) {
|
|
sfx_song_set_loops(&s->sound,
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
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:
|
|
/* sfx_all_stop(&s->sound);*/
|
|
break;
|
|
|
|
default:
|
|
warning("Unhandled DoSound command: %x", command);
|
|
|
|
}
|
|
// process_sound_events(s); /* Take care of incoming events */
|
|
|
|
return s->r_acc;
|
|
}
|
|
|
|
int sfx_send_midi(sfx_state_t *self, song_handle_t handle, int channel,
|
|
int command, int arg1, int arg2);
|
|
|
|
reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
|
uint16 command = UKPV(0);
|
|
reg_t obj = KP_ALT(1, NULL_REG);
|
|
song_handle_t handle = FROBNICATE_HANDLE(obj);
|
|
int number = obj.segment ?
|
|
GET_SEL32V(obj, number) :
|
|
-1; /* We were not going to use it anyway */
|
|
|
|
if ((s->debug_mode & (1 << SCIkSOUNDCHK_NR))
|
|
&& command != _K_SCI01_SOUND_UPDATE_CUES) {
|
|
int i;
|
|
|
|
SCIkdebug(SCIkSOUND, "Command 0x%x", command);
|
|
switch (command) {
|
|
case 0:
|
|
sciprintf("[MasterVolume]");
|
|
break;
|
|
case 1:
|
|
sciprintf("[Mute]");
|
|
break;
|
|
case 2:
|
|
sciprintf("[NOP(2)]");
|
|
break;
|
|
case 3:
|
|
sciprintf("[GetPolyphony]");
|
|
break;
|
|
case 4:
|
|
sciprintf("[Update]");
|
|
break;
|
|
case 5:
|
|
sciprintf("[Init]");
|
|
break;
|
|
case 6:
|
|
sciprintf("[Dispose]");
|
|
break;
|
|
case 7:
|
|
sciprintf("[Play]");
|
|
break;
|
|
case 8:
|
|
sciprintf("[Stop]");
|
|
break;
|
|
case 9:
|
|
sciprintf("[Suspend]");
|
|
break;
|
|
case 10:
|
|
sciprintf("[Fade]");
|
|
break;
|
|
case 11:
|
|
sciprintf("[UpdateCues]");
|
|
break;
|
|
case 12:
|
|
sciprintf("[MidiSend]");
|
|
break;
|
|
case 13:
|
|
sciprintf("[Reverb]");
|
|
break;
|
|
case 14:
|
|
sciprintf("[Hold]");
|
|
break;
|
|
default:
|
|
sciprintf("[unknown]");
|
|
break;
|
|
}
|
|
|
|
sciprintf("(");
|
|
for (i = 1; i < argc; i++) {
|
|
sciprintf(PREG, PRINT_REG(argv[i]));
|
|
if (i + 1 < argc)
|
|
sciprintf(", ");
|
|
}
|
|
sciprintf(")\n");
|
|
}
|
|
|
|
switch (command) {
|
|
case _K_SCI01_SOUND_MASTER_VOLME : {
|
|
int vol = SKPV_OR_ALT(1, -1);
|
|
|
|
if (vol != -1)
|
|
sfx_set_volume(&s->sound, vol << 0xf);
|
|
else
|
|
s->r_acc = make_reg(0, sfx_get_volume(&s->sound) >> 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) UKPV(2); /* Too lazy to look up a default value for this */
|
|
|
|
if (obj.segment) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_PLAYING);
|
|
sfx_song_set_loops(&s->sound,
|
|
handle, looping);
|
|
sfx_song_renice(&s->sound,
|
|
handle, pri);
|
|
song_lib_set_restore_behavior(s->sound.songlib, 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(kResourceTypeSound, number))) {
|
|
sciprintf("Initializing song number %d\n", number);
|
|
SCRIPT_ASSERT_ZERO(sfx_add_song(&s->sound,
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
sfx_remove_song(&s->sound, 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);
|
|
|
|
sfx_song_set_loops(&s->sound,
|
|
handle, looping);
|
|
sfx_song_renice(&s->sound, handle, pri);
|
|
|
|
SCIkdebug(SCIkSOUND, "[sound01-update-handle] -- CUE "PREG);
|
|
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
}
|
|
break;
|
|
}
|
|
case _K_SCI01_SOUND_SUSPEND_HANDLE : {
|
|
int state = UKPV(2);
|
|
int setstate = (state) ?
|
|
SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING;
|
|
|
|
if (obj.segment) {
|
|
sfx_song_set_status(&s->sound,
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
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 = sfx_poll_specific(&s->sound, handle, &cue);
|
|
|
|
switch (result) {
|
|
|
|
case SI_ABSOLUTE_CUE:
|
|
signal = cue;
|
|
SCIkdebug(SCIkSOUND, "--- [CUE] "PREG" Absolute Cue: %d\n",
|
|
PRINT_REG(obj), signal);
|
|
|
|
PUT_SEL32V(obj, signal, signal);
|
|
break;
|
|
|
|
case SI_RELATIVE_CUE:
|
|
signal = cue;
|
|
SCIkdebug(SCIkSOUND, "--- [CUE] "PREG" 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:
|
|
SCIkdebug(SCIkSOUND, "--- [FINISHED] "PREG"\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 *\/ */
|
|
/* sfx_song_set_status(&s->sound, */
|
|
/* 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 = SKPV(2);
|
|
int midiCmd = UKPV(3) == 0xff ?
|
|
0xe0 : /* Pitch wheel */
|
|
0xb0; /* UKPV(3) is actually a controller number */
|
|
int controller = UKPV(3);
|
|
int param = UKPV(4);
|
|
|
|
sfx_send_midi(&s->sound, handle,
|
|
channel, midiCmd, controller, param);
|
|
break;
|
|
}
|
|
case _K_SCI01_SOUND_REVERB : {
|
|
break;
|
|
}
|
|
case _K_SCI01_SOUND_HOLD : {
|
|
//int flag = SKPV(2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return s->r_acc;
|
|
}
|
|
|
|
int sfx_send_midi(sfx_state_t *self, song_handle_t handle, int channel,
|
|
int command, int arg1, int arg2);
|
|
|
|
reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
|
uint16 command = UKPV(0);
|
|
reg_t obj = KP_ALT(1, NULL_REG);
|
|
song_handle_t handle = FROBNICATE_HANDLE(obj);
|
|
int number = obj.segment ?
|
|
GET_SEL32V(obj, number) :
|
|
-1; /* We were not going to use it anyway */
|
|
|
|
CHECK_THIS_KERNEL_FUNCTION;
|
|
|
|
if ((s->debug_mode & (1 << SCIkSOUNDCHK_NR))
|
|
&& command != _K_SCI1_SOUND_UPDATE_CUES) {
|
|
int i;
|
|
|
|
SCIkdebug(SCIkSOUND, "Command 0x%x", command);
|
|
switch (command) {
|
|
case 0:
|
|
sciprintf("[MasterVolume]");
|
|
break;
|
|
case 1:
|
|
sciprintf("[Mute]");
|
|
break;
|
|
case 2:
|
|
sciprintf("[NOP(2)]");
|
|
break;
|
|
case 3:
|
|
sciprintf("[GetPolyphony]");
|
|
break;
|
|
case 4:
|
|
sciprintf("[GetAudioCapability]");
|
|
break;
|
|
case 5:
|
|
sciprintf("[GlobalSuspend]");
|
|
break;
|
|
case 6:
|
|
sciprintf("[Init]");
|
|
break;
|
|
case 7:
|
|
sciprintf("[Dispose]");
|
|
break;
|
|
case 8:
|
|
sciprintf("[Play]");
|
|
break;
|
|
case 9:
|
|
sciprintf("[Stop]");
|
|
break;
|
|
case 10:
|
|
sciprintf("[SuspendHandle]");
|
|
break;
|
|
case 11:
|
|
sciprintf("[Fade]");
|
|
break;
|
|
case 12:
|
|
sciprintf("[Hold]");
|
|
break;
|
|
case 13:
|
|
sciprintf("[Unused(13)]");
|
|
break;
|
|
case 14:
|
|
sciprintf("[SetVolume]");
|
|
break;
|
|
case 15:
|
|
sciprintf("[SetPriority]");
|
|
break;
|
|
case 16:
|
|
sciprintf("[SetLoop]");
|
|
break;
|
|
case 17:
|
|
sciprintf("[UpdateCues]");
|
|
break;
|
|
case 18:
|
|
sciprintf("[MidiSend]");
|
|
break;
|
|
case 19:
|
|
sciprintf("[Reverb]");
|
|
break;
|
|
case 20:
|
|
sciprintf("[UpdateVolPri]");
|
|
break;
|
|
default:
|
|
sciprintf("[unknown]");
|
|
break;
|
|
}
|
|
|
|
sciprintf("(");
|
|
for (i = 1; i < argc; i++) {
|
|
sciprintf(PREG, PRINT_REG(argv[i]));
|
|
if (i + 1 < argc)
|
|
sciprintf(", ");
|
|
}
|
|
sciprintf(")\n");
|
|
}
|
|
|
|
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 : {
|
|
return NULL_REG;
|
|
}
|
|
case _K_SCI1_SOUND_PLAY_HANDLE : {
|
|
int looping = GET_SEL32V(obj, loop);
|
|
//int vol = GET_SEL32V(obj, vol);
|
|
int pri = GET_SEL32V(obj, pri);
|
|
song_t *song = song_lib_find(s->sound.songlib, handle);
|
|
|
|
if (GET_SEL32V(obj, nodePtr) && (song && number != song->resource_num)) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
sfx_remove_song(&s->sound, handle);
|
|
PUT_SEL32(obj, nodePtr, NULL_REG);
|
|
}
|
|
|
|
if (!GET_SEL32V(obj, nodePtr) && obj.segment) {
|
|
if (!s->resmgr->testResource(kResourceTypeSound, number)) {
|
|
sciprintf("Could not open song number %d\n", number);
|
|
return NULL_REG;
|
|
}
|
|
|
|
sciprintf("Initializing song number %d\n", number);
|
|
SCRIPT_ASSERT_ZERO(sfx_add_song(&s->sound,
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_PLAYING);
|
|
sfx_song_set_loops(&s->sound,
|
|
handle, looping);
|
|
sfx_song_renice(&s->sound,
|
|
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)) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
sfx_remove_song(&s->sound, handle);
|
|
}
|
|
|
|
if (obj.segment && (s->resmgr->testResource(kResourceTypeSound, number))) {
|
|
sciprintf("Initializing song number %d\n", number);
|
|
SCRIPT_ASSERT_ZERO(sfx_add_song(&s->sound,
|
|
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) {
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
sfx_remove_song(&s->sound, handle);
|
|
}
|
|
break;
|
|
}
|
|
case _K_SCI1_SOUND_STOP_HANDLE : {
|
|
PUT_SEL32V(obj, signal, -1);
|
|
if (obj.segment) {
|
|
sfx_song_set_status(&s->sound,
|
|
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 = UKPV(2);
|
|
fade.ticks_per_step = UKPV(3);
|
|
fade.step_size = UKPV(4);
|
|
fade.action = UKPV(5) ?
|
|
FADE_ACTION_FADE_AND_STOP :
|
|
FADE_ACTION_FADE_AND_CONT;
|
|
|
|
sfx_song_set_fade(&s->sound,
|
|
handle,
|
|
&fade);
|
|
|
|
/* FIXME: The next couple of lines actually STOP the handle, rather
|
|
** than fading it! */
|
|
if (UKPV(5)) {
|
|
PUT_SEL32V(obj, signal, -1);
|
|
PUT_SEL32V(obj, nodePtr, 0);
|
|
PUT_SEL32V(obj, handle, 0);
|
|
sfx_song_set_status(&s->sound,
|
|
handle, SOUND_STATUS_STOPPED);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case _K_SCI1_SOUND_HOLD_HANDLE : {
|
|
int value = SKPV(2);
|
|
|
|
sfx_song_set_hold(&s->sound,
|
|
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 = SKPV(2);
|
|
|
|
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 = sfx_poll_specific(&s->sound, handle, &cue);
|
|
|
|
switch (result) {
|
|
|
|
case SI_ABSOLUTE_CUE:
|
|
signal = cue;
|
|
fprintf(stderr, "[CUE] "PREG" Absolute Cue: %d\n",
|
|
PRINT_REG(obj), signal);
|
|
|
|
PUT_SEL32V(obj, signal, signal);
|
|
break;
|
|
|
|
case SI_RELATIVE_CUE:
|
|
fprintf(stderr, "[CUE] "PREG" 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 : {
|
|
sfx_send_midi(&s->sound, handle,
|
|
UKPV(2), UKPV(3), UKPV(4), UKPV(5));
|
|
break;
|
|
}
|
|
case _K_SCI1_SOUND_REVERB : {
|
|
break;
|
|
}
|
|
case _K_SCI1_SOUND_UPDATE_VOL_PRI : {
|
|
break;
|
|
}
|
|
}
|
|
return s->r_acc;
|
|
}
|
|
|
|
reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
|
if (s->version >= SCI_VERSION_FTU_DOSOUND_VARIANT_2)
|
|
return kDoSound_SCI1(s, funct_nr, argc, argv);
|
|
else if (s->version >= SCI_VERSION_FTU_DOSOUND_VARIANT_1)
|
|
return kDoSound_SCI01(s, funct_nr, argc, argv);
|
|
else
|
|
return kDoSound_SCI0(s, funct_nr, argc, argv);
|
|
}
|
|
|
|
reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
|
switch (UKPV(0)) {
|
|
case _K_SCI1_AUDIO_POSITION :
|
|
return make_reg(0, -1); /* Finish immediately */
|
|
}
|
|
|
|
return s->r_acc;
|
|
}
|
|
|
|
} // End of namespace Sci
|