reg_t kMapKeyToDir(state_t *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argv[0]; if (GET_SEL32V(obj, type) == SCI_EVT_KEYBOARD) { /* Keyboard */ int mover = -1; switch (GET_SEL32V(obj, message)) { case SCI_K_HOME: mover = 8; break; case SCI_K_UP: mover = 1; break; case SCI_K_PGUP: mover = 2; break; case SCI_K_LEFT: mover = 7; break; case SCI_K_CENTER: case 76: mover = 0; break; case SCI_K_RIGHT: mover = 3; break; case SCI_K_END: mover = 6; break; case SCI_K_DOWN: mover = 5; break; case SCI_K_PGDOWN: mover = 4; break; default: break; } if (mover >= 0) { PUT_SEL32V(obj, type, SCI_EVT_JOYSTICK); PUT_SEL32V(obj, message, mover); return make_reg(0, 1); } else return NULL_REG; } return s->r_acc; }
reg_t kLocalToGlobal(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argc ? argv[0] : NULL_REG; // Can this really happen? Lars if (obj.segment) { int x = GET_SEL32V(obj, x); int y = GET_SEL32V(obj, y); PUT_SEL32V(obj, x, x + s->port->zone.x); PUT_SEL32V(obj, y, y + s->port->zone.y); } return s->r_acc; }
void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ int result; SongHandle handle; int cue; if (s->_version >= SCI_VERSION_01) return; /* SCI01 and later explicitly poll for everything */ while ((result = s->_sound.sfx_poll(&handle, &cue))) { reg_t obj = DEFROBNICATE_HANDLE(handle); if (!is_object(s, obj)) { warning("Non-object %04x:%04x received sound signal (%d/%d)", PRINT_REG(obj), result, cue); return; } switch (result) { case SI_LOOP: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x 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: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received relative cue %d\n", PRINT_REG(obj), cue); PUT_SEL32V(obj, signal, cue + 0x7f); break; case SI_ABSOLUTE_CUE: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received absolute cue %d\n", PRINT_REG(obj), cue); PUT_SEL32V(obj, signal, cue); break; case SI_FINISHED: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished\n", PRINT_REG(obj)); PUT_SEL32V(obj, signal, -1); PUT_SEL32V(obj, state, _K_SOUND_STATUS_STOPPED); break; default: warning("Unexpected result from sfx_poll: %d", result); break; } } }
reg_t kGlobalToLocal(state_t *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argc ? argv[0] : NULL_REG; /* Can this really happen? Lars */ if (obj.segment) { int x = GET_SEL32V(obj, x); int y = GET_SEL32V(obj, y); PUT_SEL32V(obj, x, x - s->port->zone.x); PUT_SEL32V(obj, y, y - s->port->zone.y); } return s->r_acc; }
reg_t kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv) { int mask = UKPV(0); reg_t obj = argv[1]; sci_event_t e; int oldx, oldy; int modifier_mask = SCI_VERSION_MAJOR(s->version)==0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK; if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) { /* Penalty time- too many requests to this function without ** waiting! */ int delay = s->script_000->locals_block->locals[SCI_VARIABLE_GAME_SPEED].offset; gfxop_usleep(s->gfx_state, (1000000 * delay) / 60); } /*If there's a simkey pending, and the game wants a keyboard event, use the *simkey instead of a normal event*/ if (_kdebug_cheap_event_hack && (mask & SCI_EVT_KEYBOARD)) { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); /*Keyboard event*/ PUT_SEL32V(obj, message, _kdebug_cheap_event_hack); PUT_SEL32V(obj, modifiers, SCI_EVM_NUMLOCK); /*Numlock on*/ PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x); PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y); _kdebug_cheap_event_hack = 0; return make_reg(0, 1); } oldx = s->gfx_state->pointer_pos.x; oldy = s->gfx_state->pointer_pos.y; e = gfxop_get_event(s->gfx_state, mask); s->parser_event = NULL_REG; /* Invalidate parser event */ PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x); PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y); /* gfxop_set_pointer_position(s->gfx_state, gfx_point(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y)); */ if (e.type) s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT); else { if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_EVENT) s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_2NDEVENT; else s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_EVENT; } switch(e.type) { case SCI_EVT_QUIT: quit_vm(); break; case SCI_EVT_KEYBOARD: { if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) { sciprintf("Debug mode activated\n"); script_debug_flag = 1; /* Enter debug mode */ _debug_seeking = _debug_step_running = 0; s->onscreen_console = 0; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { script_debug_flag = 1; /* Enter debug mode */ _debug_seeking = _debug_step_running = 0; s->onscreen_console = 1; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '1')) { if (s->visual) s->visual->print(GFXW(s->visual), 0); } else { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); /*Keyboard event*/ s->r_acc=make_reg(0, 1); PUT_SEL32V(obj, message, e.character); /* We only care about the translated ** character */ PUT_SEL32V(obj, modifiers, e.buckybits&modifier_mask); } } break; case SCI_EVT_MOUSE_RELEASE: case SCI_EVT_MOUSE_PRESS: { int extra_bits=0; if(mask & e.type) { switch(e.data) { case 2: extra_bits=SCI_EVM_LSHIFT|SCI_EVM_RSHIFT; break; case 3: extra_bits=SCI_EVM_CTRL; default:break; } PUT_SEL32V(obj, type, e.type); PUT_SEL32V(obj, message, 1); PUT_SEL32V(obj, modifiers, (e.buckybits|extra_bits)&modifier_mask); s->r_acc = make_reg(0, 1); } } break; default: { s->r_acc = NULL_REG; /* Unknown or no event */ } } if ((s->r_acc.offset) && (stop_on_event)) { stop_on_event = 0; script_debug_flag = 1; } return s->r_acc; }
reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { int mask = argv[0].toUint16(); reg_t obj = argv[1]; sci_event_t e; int oldx, oldy; int modifier_mask = s->_version <= SCI_VERSION_0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK; if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) { // Penalty time- too many requests to this function without waiting! int delay = s->script_000->locals_block->_locals[SCI_VARIABLE_GAME_SPEED].offset; gfxop_sleep(s->gfx_state, delay * 1000 / 60); } // If there's a simkey pending, and the game wants a keyboard event, use the // simkey instead of a normal event if (g_debug_simulated_key && (mask & SCI_EVT_KEYBOARD)) { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event PUT_SEL32V(obj, message, g_debug_simulated_key); PUT_SEL32V(obj, modifiers, SCI_EVM_NUMLOCK); // Numlock on PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x); PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y); g_debug_simulated_key = 0; return make_reg(0, 1); } oldx = s->gfx_state->pointer_pos.x; oldy = s->gfx_state->pointer_pos.y; e = gfxop_get_event(s->gfx_state, mask); s->parser_event = NULL_REG; // Invalidate parser event PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x); PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y); //gfxop_set_pointer_position(s->gfx_state, Common::Point(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y)); if (e.type) s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT); else { if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_EVENT) s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_2NDEVENT; else s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_EVENT; } switch (e.type) { case SCI_EVT_QUIT: quit_vm(); break; case SCI_EVT_KEYBOARD: if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) { printf("Debug mode activated\n"); scriptState.seeking = kDebugSeekNothing; scriptState.runningStep = 0; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { printf("Debug mode activated\n"); scriptState.seeking = kDebugSeekNothing; scriptState.runningStep = 0; } else { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event s->r_acc = make_reg(0, 1); PUT_SEL32V(obj, message, e.character); // We only care about the translated // character PUT_SEL32V(obj, modifiers, e.buckybits&modifier_mask); } break; case SCI_EVT_MOUSE_RELEASE: case SCI_EVT_MOUSE_PRESS: { int extra_bits = 0; // track left buttton clicks, if requested if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && g_debug_track_mouse_clicks) { ((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y); } if (mask & e.type) { switch (e.data) { case 2: extra_bits = SCI_EVM_LSHIFT | SCI_EVM_RSHIFT; break; case 3: extra_bits = SCI_EVM_CTRL; default: break; } PUT_SEL32V(obj, type, e.type); PUT_SEL32V(obj, message, 1); PUT_SEL32V(obj, modifiers, (e.buckybits | extra_bits)&modifier_mask); s->r_acc = make_reg(0, 1); } break; } default: s->r_acc = NULL_REG; // Unknown or no event } if ((s->r_acc.offset) && (scriptState.stopOnEvent)) { scriptState.stopOnEvent = false; // A SCI event occured, and we have been asked to stop, so open the debug console Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); con->DebugPrintf("SCI event occured: "); switch (e.type) { case SCI_EVT_QUIT: con->DebugPrintf("quit event\n"); break; case SCI_EVT_KEYBOARD: con->DebugPrintf("keyboard event\n"); break; case SCI_EVT_MOUSE_RELEASE: case SCI_EVT_MOUSE_PRESS: con->DebugPrintf("mouse click event\n"); break; default: con->DebugPrintf("unknown or no event (event type %d)\n", e.type); } con->attach(); con->onFrame(); } return s->r_acc; }
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; }
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; }
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; }
reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case kSciAudioSyncStart: { ResourceId id; if (s->_sound._syncResource) { s->resmgr->unlockResource(s->_sound._syncResource); s->_sound._syncResource = NULL; } // Load sound sync resource and lock it if (argc == 3) { id = ResourceId(kResourceTypeSync, argv[2].toUint16()); } else if (argc == 7) { id = ResourceId(kResourceTypeSync36, argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16(), argv[5].toUint16(), argv[6].toUint16()); } else { warning("kDoSync: Start called with an unknown number of parameters (%d)", argc); return s->r_acc; } s->_sound._syncResource = s->resmgr->findResource(id, 1); if (s->_sound._syncResource) { PUT_SEL32V(argv[1], syncCue, 0); s->_sound._syncOffset = 0; } else { warning("DoSync: failed to find resource %s", id.toString().c_str()); // Notify the scripts to stop sound sync PUT_SEL32V(argv[1], syncCue, -1); } break; } case kSciAudioSyncNext: { Resource *res = s->_sound._syncResource; if (res && (s->_sound._syncOffset < res->size - 1)) { int16 syncCue = -1; int16 syncTime = (int16)READ_LE_UINT16(res->data + s->_sound._syncOffset); s->_sound._syncOffset += 2; if ((syncTime != -1) && (s->_sound._syncOffset < res->size - 1)) { syncCue = (int16)READ_LE_UINT16(res->data + s->_sound._syncOffset); s->_sound._syncOffset += 2; } PUT_SEL32V(argv[1], syncTime, syncTime); PUT_SEL32V(argv[1], syncCue, syncCue); } break; } case kSciAudioSyncStop: if (s->_sound._syncResource) { s->resmgr->unlockResource(s->_sound._syncResource); s->_sound._syncResource = NULL; } break; default: warning("DoSync: Unhandled subfunction %d", argv[0].toUint16()); } return s->r_acc; }