/** * Poke the background palette into character 0's images. */ void FettleFontPal(SCNHANDLE fontPal) { const FONT *pFont; IMAGE *pImg; assert(fontPal); assert(g_hTagFont); // Tag font not declared assert(g_hTalkFont); // Talk font not declared pFont = (const FONT *)LockMem(g_hTagFont); pImg = (IMAGE *)LockMem(FROM_32(pFont->fontInit.hObjImg)); // get image for char 0 if (!TinselV2) pImg->hImgPal = TO_32(fontPal); else pImg->hImgPal = 0; pFont = (const FONT *)LockMem(g_hTalkFont); pImg = (IMAGE *)LockMem(FROM_32(pFont->fontInit.hObjImg)); // get image for char 0 if (!TinselV2) pImg->hImgPal = TO_32(fontPal); else pImg->hImgPal = 0; if (TinselV2 && SysVar(SV_TAGCOLOR)) { const COLORREF c = GetActorRGB(-1); SetTagColorRef(c); UpdateDACqueue(SysVar(SV_TAGCOLOR), c); } }
/** * Applies the fixed point multiplier 'mult' to all colors in * 'pOrig' to produce 'pNew'. Each color in the palette will be * multiplied by 'mult'. * @param pNew Pointer to new palette * @param pOrig Pointer to original palette * @param numColors Number of colors in the above palettes * @param mult Fixed point multiplier */ static void FadePalette(COLORREF *pNew, COLORREF *pOrig, int numColors, uint32 mult) { for (int i = 0; i < numColors; i++, pNew++, pOrig++) { if (!TinselV2) // apply multiplier to RGB components *pNew = ScaleColor(*pOrig, mult); else if (i == (TalkColor() - 1)) { *pNew = GetTalkColorRef(); *pNew = ScaleColor(*pNew, mult); } else if (SysVar(SV_TAGCOLOR) && i == (SysVar(SV_TAGCOLOR) - 1)) { *pNew = GetTagColorRef(); *pNew = ScaleColor(*pNew, mult); } else { *pNew = ScaleColor(*pOrig, mult); } } }
static void RestoreScrollDefaults() { g_sd.xTrigger = SysVar(SV_SCROLL_XTRIGGER); g_sd.xDistance = SysVar(SV_SCROLL_XDISTANCE); g_sd.xSpeed = SysVar(SV_SCROLL_XSPEED); g_sd.yTriggerTop = SysVar(SV_SCROLL_YTRIGGERTOP); g_sd.yTriggerBottom= SysVar(SV_SCROLL_YTRIGGERBOT); g_sd.yDistance = SysVar(SV_SCROLL_YDISTANCE); g_sd.ySpeed = SysVar(SV_SCROLL_YSPEED); }
void PCMMusicPlayer::dim(bool bTinselDim) { if (_dimmed || (_volume == 0) || (_state == S_IDLE) || !_curChunk || (SysVar(SV_MUSICDIMFACTOR) == 0)) return; _dimmed = true; if (bTinselDim) _dimmedTinsel = true; _dimmedVolume = _volume - (_volume / SysVar(SV_MUSICDIMFACTOR)); // Iterate down, negative iteration if (!_dimIteration) _dimPosition = _volume; _dimIteration = (_dimmedVolume - _volume)/DIM_SPEED; debugC(DEBUG_DETAILED, kTinselDebugMusic, "Dimming music from %d to %d, steps %d", _dimPosition, _dimmedVolume, _dimIteration); // And SFX if (SysVar(SYS_SceneFxDimFactor)) _vm->_sound->setSFXVolumes(255 - 255/SysVar(SYS_SceneFxDimFactor)); }
void PCMMusicPlayer::startFadeOut(int ticks) { if ((_volume == 0) || (_state == S_IDLE) || !_curChunk) return; debugC(DEBUG_INTERMEDIATE, kTinselDebugMusic, "Fading out music..."); if (_dimmed) { // Start from dimmed volume and go from there _dimmed = false; _fadeOutVolume = _volume - _volume/SysVar(SV_MUSICDIMFACTOR); } else _fadeOutVolume = _volume; assert(ticks != 0); _fadeOutIteration = _fadeOutVolume / ticks; fadeOutIteration(); }
void PrimeScene() { SetNoBlocking(false); SetSysVar(SYS_SceneFxDimFactor, SysVar(SYS_DefaultFxDimFactor)); RestartCursor(); // Restart the cursor if (!TinselV2) EnableTags(); // Next scene with tags enabled g_scheduler->createProcess(PID_SCROLL, ScrollProcess, NULL, 0); g_scheduler->createProcess(PID_SCROLL, EffectPolyProcess, NULL, 0); #ifdef DEBUG if (ShowPosition) g_scheduler->createProcess(PID_POSITION, CursorPositionProcess, NULL, 0); #endif g_scheduler->createProcess(PID_TAG, TagProcess, NULL, 0); g_scheduler->createProcess(PID_TAG, PointProcess, NULL, 0); // init the current background PrimeBackground(); }
/** * Stand all the moving actors at their saved positions. * Not called from the foreground. */ static void SortMAProcess(CORO_PARAM, const void *) { CORO_BEGIN_CONTEXT; int i; int viaActor; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // Disable via actor for the stands _ctx->viaActor = SysVar(ISV_DIVERT_ACTOR); SetSysVar(ISV_DIVERT_ACTOR, 0); RestoreAuxScales(rsd->SavedMoverInfo); for (_ctx->i = 0; _ctx->i < MAX_MOVERS; _ctx->i++) { if (rsd->SavedMoverInfo[_ctx->i].bActive) { CORO_INVOKE_ARGS(Stand, (CORO_SUBCTX, rsd->SavedMoverInfo[_ctx->i].actorID, rsd->SavedMoverInfo[_ctx->i].objX, rsd->SavedMoverInfo[_ctx->i].objY, rsd->SavedMoverInfo[_ctx->i].hLastfilm)); if (rsd->SavedMoverInfo[_ctx->i].bHidden) HideMover(GetMover(rsd->SavedMoverInfo[_ctx->i].actorID)); } ActorPalette(rsd->SavedMoverInfo[_ctx->i].actorID, rsd->SavedMoverInfo[_ctx->i].startColour, rsd->SavedMoverInfo[_ctx->i].paletteLength); if (rsd->SavedMoverInfo[_ctx->i].brightness != BOGUS_BRIGHTNESS) ActorBrightness(rsd->SavedMoverInfo[_ctx->i].actorID, rsd->SavedMoverInfo[_ctx->i].brightness); } // Restore via actor SetSysVar(ISV_DIVERT_ACTOR, _ctx->viaActor); bNotDoneYet = false; CORO_END_CODE; }
bool ActorIsGhost(int actor) { return actor == SysVar(ISV_GHOST_ACTOR); }
/** * Called from scroll process - Scrolls the image as appropriate. */ static void ScrollImage() { int OldLoffset = 0, OldToffset = 0; // Used when keeping cursor on a tag int Loffset, Toffset; int curX, curY; // get background offsets PlayfieldGetPos(FIELD_WORLD, &Loffset, &Toffset); /* * Keeping cursor on a tag? */ if (g_ScrollCursor) { GetCursorXYNoWait(&curX, &curY, true); if (InPolygon(curX, curY, TAG) != NOPOLY || InPolygon(curX, curY, EXIT) != NOPOLY) { OldLoffset = Loffset; OldToffset = Toffset; } else g_ScrollCursor = false; } /* * Horizontal scrolling */ if (g_LeftScroll > 0) { g_LeftScroll -= g_scrollPixelsX; if (g_LeftScroll < 0) { Loffset += g_LeftScroll; g_LeftScroll = 0; } Loffset += g_scrollPixelsX; // Move right if (Loffset > g_ImageW - SCREEN_WIDTH) Loffset = g_ImageW - SCREEN_WIDTH;// Now at extreme right /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MaximumXoffset) && (Loffset > SysVar(SV_MaximumXoffset))) Loffset = SysVar(SV_MaximumXoffset); } else if (g_LeftScroll < 0) { g_LeftScroll += g_scrollPixelsX; if (g_LeftScroll > 0) { Loffset += g_LeftScroll; g_LeftScroll = 0; } Loffset -= g_scrollPixelsX; // Move left if (Loffset < 0) Loffset = 0; // Now at extreme left /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MinimumXoffset) && (Loffset < SysVar(SV_MinimumXoffset))) Loffset = SysVar(SV_MinimumXoffset); } /* * Vertical scrolling */ if (g_DownScroll > 0) { g_DownScroll -= g_scrollPixelsY; if (g_DownScroll < 0) { Toffset += g_DownScroll; g_DownScroll = 0; } Toffset += g_scrollPixelsY; // Move down if (Toffset > g_ImageH - SCREEN_HEIGHT) Toffset = g_ImageH - SCREEN_HEIGHT;// Now at extreme bottom /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MaximumYoffset) && Toffset > SysVar(SV_MaximumYoffset)) Toffset = SysVar(SV_MaximumYoffset); } else if (g_DownScroll < 0) { g_DownScroll += g_scrollPixelsY; if (g_DownScroll > 0) { Toffset += g_DownScroll; g_DownScroll = 0; } Toffset -= g_scrollPixelsY; // Move up if (Toffset < 0) Toffset = 0; // Now at extreme top /*** New feature to prop up rickety scroll boundaries ***/ if (TinselV2 && SysVar(SV_MinimumYoffset) && Toffset < SysVar(SV_MinimumYoffset)) Toffset = SysVar(SV_MinimumYoffset); } /* * Move cursor if keeping cursor on a tag. */ if (g_ScrollCursor) AdjustCursorXY(OldLoffset - Loffset, OldToffset - Toffset); PlayfieldSetPos(FIELD_WORLD, Loffset, Toffset); }
void PokeInTagColor() { if (SysVar(SV_TAGCOLOR)) { const COLORREF c = GetActorRGB(-1); UpdateDACqueue(SysVar(SV_TAGCOLOR), c); } }
// playSample for DiscWorld 2 bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int priority, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { // Floppy version has no sample file if (_vm->getFeatures() & GF_FLOPPY) return false; // no sample driver? if (!_vm->_mixer->isReady()) return false; Channel *curChan; uint8 sndVol = 255; // Sample on screen? if (!offscreenChecks(x, y)) return false; // If that sample is already playing, stop it stopSpecSample(id, sub); if (type == Audio::Mixer::kSpeechSoundType) { curChan = &_channels[kChannelTalk]; } else if (type == Audio::Mixer::kSFXSoundType) { uint32 oldestTime = g_system->getMillis(); int oldestChan = kChannelSFX; int chan; for (chan = kChannelSFX; chan < kNumChannels; chan++) { if (!_vm->_mixer->isSoundHandleActive(_channels[chan].handle)) break; if ((_channels[chan].lastStart < oldestTime) && (_channels[chan].priority <= priority)) { oldestTime = _channels[chan].lastStart; oldestChan = chan; } } if (chan == kNumChannels) { if (_channels[oldestChan].priority > priority) { warning("playSample: No free channel"); return false; } chan = oldestChan; } if (_vm->_pcmMusic->isDimmed() && SysVar(SYS_SceneFxDimFactor)) sndVol = 255 - 255/SysVar(SYS_SceneFxDimFactor); curChan = &_channels[chan]; } else { warning("playSample: Unknown SoundType"); return false; } // stop any currently playing sample _vm->_mixer->stopHandle(curChan->handle); // make sure id is in range assert(id > 0 && id < _sampleIndexLen); // get file offset for this sample uint32 dwSampleIndex = _sampleIndex[id]; if (dwSampleIndex == 0) { warning("Tinsel2 playSample, non-existant sample %d", id); return false; } // move to correct position in the sample file _sampleStream.seek(dwSampleIndex); if (_sampleStream.eos() || _sampleStream.err() || (uint32)_sampleStream.pos() != dwSampleIndex) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); // read the length of the sample uint32 sampleLen = _sampleStream.readUint32(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); if (sampleLen & 0x80000000) { // Has sub samples int32 numSubs = sampleLen & ~0x80000000; assert(sub >= 0 && sub < numSubs); // Skipping for (int32 i = 0; i < sub; i++) { sampleLen = _sampleStream.readUint32(); _sampleStream.skip(sampleLen); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); } sampleLen = _sampleStream.readUint32(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); } debugC(DEBUG_DETAILED, kTinselDebugSound, "Playing sound %d.%d, %d bytes at %d (pan %d)", id, sub, sampleLen, _sampleStream.pos(), getPan(x)); // allocate a buffer byte *sampleBuf = (byte *) malloc(sampleLen); assert(sampleBuf); // read all of the sample if (_sampleStream.read(sampleBuf, sampleLen) != sampleLen) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); Common::MemoryReadStream *compressedStream = new Common::MemoryReadStream(sampleBuf, sampleLen, DisposeAfterUse::YES); Audio::AudioStream *sampleStream = 0; switch (_soundMode) { case kMP3Mode: #ifdef USE_MAD sampleStream = Audio::makeMP3Stream(compressedStream, DisposeAfterUse::YES); #endif break; case kVorbisMode: #ifdef USE_VORBIS sampleStream = Audio::makeVorbisStream(compressedStream, DisposeAfterUse::YES); #endif break; case kFLACMode: #ifdef USE_FLAC sampleStream = Audio::makeFLACStream(compressedStream, DisposeAfterUse::YES); #endif break; default: sampleStream = Audio::makeADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); break; } // FIXME: Should set this in a different place ;) bool mute = false; if (ConfMan.hasKey("mute")) mute = ConfMan.getBool("mute"); _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : _vm->_config->_soundVolume); //_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : _vm->_config->_voiceVolume); curChan->sampleNum = id; curChan->subSample = sub; curChan->looped = bLooped; curChan->x = x; curChan->y = y; curChan->priority = priority; curChan->lastStart = g_system->getMillis(); // /---Compression----\ Milis BytesPerSecond // not needed and won't work when using MP3/OGG/FLAC anyway //curChan->timeDuration = (((sampleLen * 64) / 25) * 1000) / (22050 * 2); // Play it _vm->_mixer->playStream(type, &curChan->handle, sampleStream); _vm->_mixer->setChannelVolume(curChan->handle, sndVol); _vm->_mixer->setChannelBalance(curChan->handle, getPan(x)); if (handle) *handle = curChan->handle; return true; }
/** * Gets the no blocking flag. Note that for convenience, the systemVars array * entry is used even for Tinsel 1, which originally used a separate variable. */ bool GetNoBlocking() { return SysVar(ISV_NO_BLOCKING); }