void GfxCompare::kernelBaseSetter(reg_t object) { if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) { int16 x = readSelectorValue(_segMan, object, SELECTOR(x)); int16 y = readSelectorValue(_segMan, object, SELECTOR(y)); int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0; int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep)); GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view)); int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop)); int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel)); uint16 scaleSignal = 0; if (getSciVersion() >= SCI_VERSION_1_1) scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal)); Common::Rect celRect; GfxView *tmpView = _cache->getView(viewId); if (!tmpView->isScaleable()) scaleSignal = 0; if (scaleSignal & kScaleSignalDoScaling) { celRect = getNSRect(object); } else { tmpView->getCelRect(loopNo, celNo, x, y, z, celRect); } celRect.bottom = y + 1; celRect.top = celRect.bottom - yStep; writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left); writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right); writeSelectorValue(_segMan, object, SELECTOR(brTop), celRect.top); writeSelectorValue(_segMan, object, SELECTOR(brBottom), celRect.bottom); } }
void GuestAdditions::syncGK1StartupVolumeFromScummVM(const int index, const reg_t value) const { if (index == kGlobalVarGK1Music1 || index == kGlobalVarGK1Music2 || index == kGlobalVarGK1DAC1 || index == kGlobalVarGK1DAC2 || index == kGlobalVarGK1DAC3) { int16 volume; Selector selector; switch (readSelectorValue(_segMan, value, SELECTOR(type))) { case kSoundsMusicType: { volume = (ConfMan.getInt("music_volume") + 1) * MUSIC_VOLUME_MAX / Audio::Mixer::kMaxMixerVolume; selector = SELECTOR(musicVolume); break; } case kSoundsSoundType: { volume = (ConfMan.getInt("sound_volume") + 1) * MUSIC_VOLUME_MAX / Audio::Mixer::kMaxMixerVolume; selector = SELECTOR(soundVolume); break; } default: error("Unknown sound type"); } writeSelectorValue(_segMan, value, selector, volume); writeSelectorValue(_segMan, value, selector, volume); } }
void GuestAdditions::syncGK1VolumeFromScummVM(const int16 musicVolume, const int16 dacVolume) const { const reg_t soundsId = _state->variables[VAR_GLOBAL][kGlobalVarSounds]; if (!soundsId.isNull()) { List *sounds = _segMan->lookupList(readSelector(_segMan, soundsId, SELECTOR(elements))); reg_t soundId = sounds->first; while (!soundId.isNull()) { Node *sound = _segMan->lookupNode(soundId); const int16 type = readSelectorValue(_segMan, sound->value, SELECTOR(type)); int16 volume; if (type == kSoundsMusicType) { volume = ConfMan.getBool("mute") ? 0 : musicVolume; writeSelectorValue(_segMan, sound->value, SELECTOR(musicVolume), musicVolume); } else if (type == kSoundsSoundType) { volume = dacVolume; writeSelectorValue(_segMan, sound->value, SELECTOR(soundVolume), dacVolume); } else { error("Unknown sound type %d", type); } // `setVolume` will set the `vol` property on the sound object; // if it did not do this, an invocation of the `setVol` selector // would need to be here (though doing so would result in // recursion, so don't) g_sci->_soundCmd->setVolume(sound->value, volume); soundId = sound->succ; } } }
void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(stop): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } if (_soundVersion <= SCI_VERSION_0_LATE) { writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); } else { writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); } // Set signal selector in sound SCI0 games only, when the sample has // finished playing. If we don't set it at all, we get a problem when using // vaporizer on the 2 guys. If we set it all the time, we get no music in // sq3new and kq1. // FIXME: This *may* be wrong, it's impossible to find out in Sierra DOS // SCI, because SCI0 under DOS didn't have sfx drivers included. // We need to set signal in sound SCI1+ games all the time. if ((_soundVersion > SCI_VERSION_0_LATE) || sampleFinishedPlaying) writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); musicSlot->dataInc = 0; musicSlot->signal = SIGNAL_OFFSET; _music->soundStop(musicSlot); }
reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; int16 value = argv[1].toSint16(); debugC(kDebugLevelSound, "kDoSound(setPriority): %04x:%04x, %d", PRINT_REG(obj), value); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { debugC(kDebugLevelSound, "kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } if (value == -1) { uint16 resourceId = musicSlot->resourceId; // Set priority from the song data Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0); if (song->data[0] == 0xf0) _music->soundSetPriority(musicSlot, song->data[1]); else warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value"); //pSnd->prio=0;field_15B=0 writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD); } else { // Scripted priority //pSnd->field_15B=1; writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); //DoSOund(0xF,hobj,w) } return acc; }
void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { AnimateList::iterator it; const AnimateList::iterator end = _list.end(); // This has to be done in a separate loop. At least in sq1 some .dispose // modifies FIXEDLOOP flag in signal for another object. In that case we // would overwrite the new signal with our version of the old signal. for (it = _list.begin(); it != end; ++it) { // Finally update signal writeSelectorValue(_s->_segMan, it->object, SELECTOR(signal), it->signal); } for (it = _list.legacy_reverse_begin(); it != end; --it) { // We read out signal here again, this is not by accident but to ensure // that we got an up-to-date signal it->signal = readSelectorValue(_s->_segMan, it->object, SELECTOR(signal)); if ((it->signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) { _paint16->bitsRestore(readSelector(_s->_segMan, it->object, SELECTOR(underBits))); writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0); } if (it->signal & kSignalDisposeMe) { // Call .delete_ method of that object invokeSelector(_s, it->object, SELECTOR(delete_), argc, argv, 0); } } }
void SciEngine::setLauncherLanguage() { if (_gameDescription->flags & ADGF_ADDENGLISH) { // If game is multilingual Common::Language chosenLanguage = Common::parseLanguage(ConfMan.get("language")); uint16 languageToSet = 0; switch (chosenLanguage) { case Common::EN_ANY: // and English was selected as language languageToSet = K_LANG_ENGLISH; break; case Common::JA_JPN: { // Set Japanese for FM-Towns games // KQ5 on FM-Towns has no initial language set if (g_sci->getPlatform() == Common::kPlatformFMTowns) { languageToSet = K_LANG_JAPANESE; } } default: break; } if (languageToSet) { if (SELECTOR(printLang) != -1) // set text language writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(printLang), languageToSet); if (SELECTOR(parseLang) != -1) // and set parser language as well writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(parseLang), languageToSet); } } }
reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[0]; SegManager *segMan = s->_segMan; if (readSelectorValue(segMan, obj, SELECTOR(type)) == SCI_EVENT_KEYBOARD) { // Keyboard uint16 message = readSelectorValue(segMan, obj, SELECTOR(message)); uint16 eventType = SCI_EVENT_DIRECTION; // Check if the game is using cursor views. These games allowed control // of the mouse cursor via the keyboard controls (the so called // "PseudoMouse" functionality in script 933). if (g_sci->_features->detectSetCursorType() == SCI_VERSION_1_1) eventType |= SCI_EVENT_KEYBOARD; for (int i = 0; i < 9; i++) { if (keyToDirMap[i].key == message) { writeSelectorValue(segMan, obj, SELECTOR(type), eventType); writeSelectorValue(segMan, obj, SELECTOR(message), keyToDirMap[i].direction); return TRUE_REG; // direction mapped } } return NULL_REG; // unknown direction } return s->r_acc; // no keyboard event to map, leave accumulator unchanged }
void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) { // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY int16 maxScale = readSelectorValue(_s->_segMan, entry->object, SELECTOR(maxScale)); int16 celHeight = view->getHeight(entry->loopNo, entry->celNo); int16 maxCelHeight = (maxScale * celHeight) >> 7; reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY)); int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY; int16 fixedEntryY = entry->y - vanishingY; if (!fixedEntryY) fixedEntryY = 1; if ((celHeight == 0) || (fixedPortY == 0)) error("global scaling panic"); entry->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY; entry->scaleY = (entry->scaleY * 128) / celHeight; entry->scaleX = entry->scaleY; // and set objects scale selectors writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleX), entry->scaleX); writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleY), entry->scaleY); }
void GfxAnimate::adjustInvalidCels(GfxView *view, AnimateList::iterator it) { // adjust loop and cel, if any of those is invalid // this seems to be completely crazy code // sierra sci checked signed int16 to be above or equal the counts and reseted to 0 in those cases // later during view processing those are compared unsigned again and then set to maximum count - 1 // Games rely on this behavior. For example laura bow 1 has a knight standing around in room 37 // which has cel set to 3. This cel does not exist and the actual knight is 0 // In kq5 on the other hand during the intro, when the trunk is opened, cel is set to some real // high number, which is negative when considered signed. This actually requires to get fixed to // maximum cel, otherwise the trunk would be closed. int16 viewLoopCount = view->getLoopCount(); if (it->loopNo >= viewLoopCount) { it->loopNo = 0; writeSelectorValue(_s->_segMan, it->object, SELECTOR(loop), it->loopNo); } else if (it->loopNo < 0) { it->loopNo = viewLoopCount - 1; // not setting selector is right, sierra sci didn't do it during view processing as well } int16 viewCelCount = view->getCelCount(it->loopNo); if (it->celNo >= viewCelCount) { it->celNo = 0; writeSelectorValue(_s->_segMan, it->object, SELECTOR(cel), it->celNo); } else if (it->celNo < 0) { it->celNo = viewCelCount - 1; } }
void SciEngine::setLauncherLanguage() { if (_gameDescription->flags & ADGF_ADDENGLISH) { // If game is multilingual if (Common::parseLanguage(ConfMan.get("language")) == Common::EN_ANY) { // and English was selected as language if (SELECTOR(printLang) != -1) // set text language to English writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(printLang), K_LANG_ENGLISH); if (SELECTOR(parseLang) != -1) // and set parser language to English as well writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(parseLang), K_LANG_ENGLISH); } } }
void GuestAdditions::syncLSL6HiresUI(const int16 musicVolume) const { const reg_t musicDialId = _segMan->findObjectByName("volumeDial"); if (!musicDialId.isNull()) { writeSelectorValue(_segMan, musicDialId, SELECTOR(curPos), musicVolume); writeSelectorValue(_segMan, musicDialId, SELECTOR(cel), musicVolume); reg_t params[] = { make_reg(0, musicVolume) }; invokeSelector(musicDialId, SELECTOR(update), 1, params); if (_segMan->getObject(musicDialId)->isInserted()) { g_sci->_gfxFrameout->kernelUpdateScreenItem(musicDialId); } } }
void SoundCommandParser::processPlaySound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(play): Slot not found (%04x:%04x), initializing it manually", PRINT_REG(obj)); // The sound hasn't been initialized for some reason, so initialize it // here. Happens in KQ6, room 460, when giving the creature (child) to // the bookworm. Fixes bugs #3413301 and #3421098. processInitSound(obj); musicSlot = _music->getSlot(obj); if (!musicSlot) error("Failed to initialize uninitialized sound slot"); } int resourceId = getSoundResourceId(obj); if (musicSlot->resourceId != resourceId) { // another sound loaded into struct processDisposeSound(obj); processInitSound(obj); // Find slot again :) musicSlot = _music->getSlot(obj); } writeSelector(_segMan, obj, SELECTOR(handle), obj); if (_soundVersion >= SCI_VERSION_1_EARLY) { writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); writeSelectorValue(_segMan, obj, SELECTOR(min), 0); writeSelectorValue(_segMan, obj, SELECTOR(sec), 0); writeSelectorValue(_segMan, obj, SELECTOR(frame), 0); writeSelectorValue(_segMan, obj, SELECTOR(signal), 0); } else { writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundPlaying); } musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); // Reset hold when starting a new song. kDoSoundSetHold is always called after // kDoSoundPlay to set it properly, if needed. Fixes bug #3413589. musicSlot->hold = -1; if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume); _music->soundPlay(musicSlot); // Reset any left-over signals musicSlot->signal = 0; musicSlot->fadeStep = 0; }
void GfxCompare::kernelBaseSetter(reg_t object) { if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) { int16 x = readSelectorValue(_segMan, object, SELECTOR(x)); int16 y = readSelectorValue(_segMan, object, SELECTOR(y)); int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0; int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep)); GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view)); int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop)); int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel)); // HACK: Ignore invalid views for now (perhaps unimplemented text views?) if (viewId == 0xFFFF) // invalid view return; uint16 scaleSignal = 0; if (getSciVersion() >= SCI_VERSION_1_1) { scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal)); } Common::Rect celRect; GfxView *tmpView = _cache->getView(viewId); if (!tmpView->isScaleable()) scaleSignal = 0; if (scaleSignal & kScaleSignalDoScaling) { celRect = getNSRect(object); } else { if (tmpView->isSci2Hires()) tmpView->adjustToUpscaledCoordinates(y, x); tmpView->getCelRect(loopNo, celNo, x, y, z, celRect); if (tmpView->isSci2Hires()) { tmpView->adjustBackUpscaledCoordinates(celRect.top, celRect.left); tmpView->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right); } } celRect.bottom = y + 1; celRect.top = celRect.bottom - yStep; writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left); writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right); writeSelectorValue(_segMan, object, SELECTOR(brTop), celRect.top); writeSelectorValue(_segMan, object, SELECTOR(brBottom), celRect.bottom); } }
void GfxAnimate::fill(byte &old_picNotValid) { GfxView *view = NULL; AnimateList::iterator it; const AnimateList::iterator end = _list.end(); for (it = _list.begin(); it != end; ++it) { // Get the corresponding view view = _cache->getView(it->viewId); adjustInvalidCels(view, it); processViewScaling(view, it); setNsRect(view, it); //warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal); // Calculate current priority according to y-coordinate if (!(it->signal & kSignalFixedPriority)) { it->priority = _ports->kernelCoordinateToPriority(it->y); writeSelectorValue(_s->_segMan, it->object, SELECTOR(priority), it->priority); } if (it->signal & kSignalNoUpdate) { if ((it->signal & (kSignalForceUpdate | kSignalViewUpdated)) || (it->signal & kSignalHidden && !(it->signal & kSignalRemoveView)) || (!(it->signal & kSignalHidden) && it->signal & kSignalRemoveView) || (it->signal & kSignalAlwaysUpdate)) old_picNotValid++; it->signal &= ~kSignalStopUpdate; } else { if ((it->signal & kSignalStopUpdate) || (it->signal & kSignalAlwaysUpdate)) old_picNotValid++; it->signal &= ~kSignalForceUpdate; } } }
void SoundCommandParser::processInitSound(reg_t obj) { int resourceId = getSoundResourceId(obj); // Check if a track with the same sound object is already playing MusicEntry *oldSound = _music->getSlot(obj); if (oldSound) processDisposeSound(obj); MusicEntry *newSound = new MusicEntry(); newSound->resourceId = resourceId; newSound->soundObj = obj; newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF; if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); newSound->reverb = -1; // initialize to SCI invalid, it'll be set correctly in soundInitSnd() below debugC(kDebugLevelSound, "kDoSound(init): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), resourceId, newSound->loop, newSound->priority, newSound->volume); initSoundResource(newSound); _music->pushBackSlot(newSound); if (newSound->soundRes || newSound->pStreamAud) { // Notify the engine if (_soundVersion <= SCI_VERSION_0_LATE) writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized); else writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); } }
reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; int16 value = argv[1].toSint16(); debugC(kDebugLevelSound, "kDoSound(setLoop): %04x:%04x, %d", PRINT_REG(obj), value); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Apparently, it's perfectly normal for a game to call cmdSetSoundLoop // before actually initializing the sound and adding it to the playlist // with cmdInitSound. Usually, it doesn't matter if the game doesn't // request to loop the sound, so in this case, don't throw any warning, // otherwise do, because the sound won't be looped. if (value == -1) { warning("kDoSound(setLoop): Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); } else { // Doesn't really matter } return acc; } if (value == -1) { musicSlot->loop = 0xFFFF; } else { musicSlot->loop = 1; // actually plays the music once } writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); return acc; }
void SoundCommandParser::processDisposeSound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(dispose): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } processStopSound(obj, false); _music->soundKill(musicSlot); writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); if (_soundVersion >= SCI_VERSION_1_EARLY) writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); else writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); }
reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; int16 value = argv[1].toSint16(); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Do not throw a warning if the sound can't be found, as in some games // this is called before the actual sound is loaded (e.g. SQ4CD, with // the drum sounds of the energizer bunny at the beginning), so this is // normal behavior. //warning("cmdSetSoundVolume: Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } debugC(kDebugLevelSound, "kDoSound(setVolume): %d", value); value = CLIP<int>(value, 0, MUSIC_VOLUME_MAX); if (musicSlot->volume != value) { musicSlot->volume = value; _music->soundSetVolume(musicSlot, value); writeSelectorValue(_segMan, obj, SELECTOR(vol), value); } return acc; }
reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[0]; reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32 SegManager *segMan = s->_segMan; if (obj.getSegment()) { int16 x = readSelectorValue(segMan, obj, SELECTOR(x)); int16 y = readSelectorValue(segMan, obj, SELECTOR(y)); g_sci->_gfxCoordAdjuster->kernelLocalToGlobal(x, y, planeObject); writeSelectorValue(segMan, obj, SELECTOR(x), x); writeSelectorValue(segMan, obj, SELECTOR(y), y); } return s->r_acc; }
reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { if (argc == 1) debugC(kDebugLevelSound, "kDoSound(pause): %04x:%04x", PRINT_REG(argv[0])); else debugC(kDebugLevelSound, "kDoSound(pause): %04x:%04x, %04x:%04x", PRINT_REG(argv[0]), PRINT_REG(argv[1])); if (_soundVersion <= SCI_VERSION_0_LATE) { // SCI0 games give us 0/1 for either resuming or pausing the current music // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume uint16 value = argv[0].toUint16(); MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); switch (value) { case 1: if ((musicSlot) && (musicSlot->status == kSoundPlaying)) { _music->soundPause(musicSlot); writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused); } return make_reg(0, 0); case 0: if ((musicSlot) && (musicSlot->status == kSoundPaused)) { _music->soundResume(musicSlot); writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); return make_reg(0, 1); } return make_reg(0, 0); default: error("kDoSound(pause): parameter 0 is invalid for sound-sci0"); } } reg_t obj = argv[0]; uint16 value = argc > 1 ? argv[1].toUint16() : 0; if (!obj.segment) { // pause the whole playlist _music->pauseAll(value); } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // This happens quite frequently debugC(kDebugLevelSound, "kDoSound(pause): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } _music->soundToggle(musicSlot, value); } return acc; }
void GuestAdditions::syncShivers1UI(const int16 dacVolume) const { const reg_t sliderId = _segMan->findObjectByName("spVolume"); if (!sliderId.isNull()) { const int16 xPosition = dacVolume * 78 / Audio32::kMaxVolume + 32; writeSelectorValue(_segMan, sliderId, SELECTOR(x), xPosition); if (_segMan->getObject(sliderId)->isInserted()) { g_sci->_gfxFrameout->kernelUpdateScreenItem(sliderId); } } }
void SoundCommandParser::startNewSound(int number) { Common::StackLock lock(_music->_mutex); // Overwrite the first sound in the playlist MusicEntry *song = *_music->getPlayListStart(); reg_t soundObj = song->soundObj; processDisposeSound(soundObj); writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); processInitSound(soundObj); processPlaySound(soundObj); }
void GfxAnimate::updateScreen(byte oldPicNotValid) { AnimateList::iterator it; const AnimateList::iterator end = _list.end(); Common::Rect lsRect; Common::Rect workerRect; for (it = _list.begin(); it != end; ++it) { if (it->showBitsFlag || !(it->signal & (kSignalRemoveView | kSignalNoUpdate) || (!(it->signal & kSignalRemoveView) && (it->signal & kSignalNoUpdate) && oldPicNotValid))) { lsRect.left = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft)); lsRect.top = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop)); lsRect.right = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight)); lsRect.bottom = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom)); workerRect = lsRect; workerRect.clip(it->celRect); if (!workerRect.isEmpty()) { workerRect = lsRect; workerRect.extend(it->celRect); } else { _paint16->bitsShow(lsRect); workerRect = it->celRect; } writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft), it->celRect.left); writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop), it->celRect.top); writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight), it->celRect.right); writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom), it->celRect.bottom); // may get used for debugging //_paint16->frameRect(workerRect); _paint16->bitsShow(workerRect); if (it->signal & kSignalHidden) it->signal |= kSignalRemoveView; } } // use this for debug purposes // _screen->copyToScreen(); }
reg_t SoundCommandParser::kDoSoundStopAll(int argc, reg_t *argv, reg_t acc) { // TODO: this can't be right, this gets called in kq1 - e.g. being in witch house, getting the note // now the point jingle plays and after a messagebox they call this - and would stop the background effects with it // this doesn't make sense, so i disable it for now return acc; Common::StackLock(_music->_mutex); const MusicList::iterator end = _music->getPlayListEnd(); for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { if (_soundVersion <= SCI_VERSION_0_LATE) { writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(state), kSoundStopped); } else { writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(handle), 0); writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal), SIGNAL_OFFSET); } (*i)->dataInc = 0; _music->soundStop(*i); } return acc; }
reg_t kSort(EngineState *s, int argc, reg_t *argv) { SegManager *segMan = s->_segMan; reg_t source = argv[0]; reg_t dest = argv[1]; reg_t order_func = argv[2]; int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size)); reg_t input_data = readSelector(segMan, source, SELECTOR(elements)); reg_t output_data = readSelector(segMan, dest, SELECTOR(elements)); List *list; Node *node; if (!input_size) return s->r_acc; if (output_data.isNull()) { list = s->_segMan->allocateList(&output_data); list->first = list->last = NULL_REG; writeSelector(segMan, dest, SELECTOR(elements), output_data); } writeSelectorValue(segMan, dest, SELECTOR(size), input_size); list = s->_segMan->lookupList(input_data); node = s->_segMan->lookupNode(list->first); sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size); int i = 0; while (node) { reg_t params[1] = { node->value }; invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params); temp_array[i].key = node->key; temp_array[i].value = node->value; temp_array[i].order = s->r_acc; i++; node = s->_segMan->lookupNode(node->succ); } qsort(temp_array, input_size, sizeof(sort_temp_t), sort_temp_cmp); for (i = 0;i < input_size;i++) { reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key); addToEnd(s, output_data, lNode); } free(temp_array); return s->r_acc; }
void GuestAdditions::syncTextSpeedFromScummVM() const { const int16 textSpeed = 8 - (ConfMan.getInt("talkspeed") + 1) * 8 / 255; _state->variables[VAR_GLOBAL][kGlobalVarTextSpeed] = make_reg(0, textSpeed); if (g_sci->getGameId() == GID_GK1) { const reg_t textBarId = _segMan->findObjectByName("textBar"); if (!textBarId.isNull()) { // Resetting the bar position to 0 causes the game to retrieve the // new text speed value and re-render writeSelectorValue(_segMan, textBarId, SELECTOR(position), 0); } } }
void GuestAdditions::syncQFG4UI(const int16 musicVolume) const { const reg_t sliderId = _segMan->findObjectByName("volumeSlider"); if (!sliderId.isNull()) { const int16 yPosition = 84 - musicVolume * 34 / 10; writeSelectorValue(_segMan, sliderId, SELECTOR(y), yPosition); // There does not seem to be any good way to learn whether the // volume slider is visible (and thus eligible for // kUpdateScreenItem) const reg_t planeId = readSelector(_segMan, sliderId, SELECTOR(plane)); if (g_sci->_gfxFrameout->getPlanes().findByObject(planeId) != nullptr) { g_sci->_gfxFrameout->kernelUpdateScreenItem(sliderId); } } }
reg_t kSaid(EngineState *s, int argc, reg_t *argv) { reg_t heap_said_block = argv[0]; byte *said_block; int new_lastmatch; Vocabulary *voc = g_sci->getVocabulary(); #ifdef DEBUG_PARSER const int debug_parser = 1; #else const int debug_parser = 0; #endif if (!heap_said_block.getSegment()) return NULL_REG; said_block = (byte *)s->_segMan->derefBulkPtr(heap_said_block, 0); if (!said_block) { warning("Said on non-string, pointer %04x:%04x", PRINT_REG(heap_said_block)); return NULL_REG; } #ifdef DEBUG_PARSER debugN("Said block: "); g_sci->getVocabulary()->debugDecipherSaidBlock(said_block); #endif if (voc->parser_event.isNull() || (readSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed)))) { return NULL_REG; } new_lastmatch = said(said_block, debug_parser); if (new_lastmatch != SAID_NO_MATCH) { /* Build and possibly display a parse tree */ #ifdef DEBUG_PARSER debugN("kSaid: Match.\n"); #endif s->r_acc = make_reg(0, 1); if (new_lastmatch != SAID_PARTIAL_MATCH) writeSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed), 1); } else { return NULL_REG; } return s->r_acc; }
void GuestAdditions::syncGK1UI() const { const reg_t bars[] = { _segMan->findObjectByName("musicBar"), _segMan->findObjectByName("soundBar") }; for (int i = 0; i < ARRAYSIZE(bars); ++i) { const reg_t barId = bars[i]; if (!barId.isNull()) { // Resetting the position to 0 causes the bar to refresh its // position when it next draws writeSelectorValue(_segMan, barId, SELECTOR(position), 0); // The `signal` property indicates bar visibility (for some // reason, the normal `-info-` flag is not used) if (readSelectorValue(_segMan, barId, SELECTOR(signal)) & 0x20) { // `show` pulls a new value from the underlying sound object // and refreshes the bar rendering invokeSelector(barId, SELECTOR(show)); } } } }