/** * Called at the start of each scene for each actor with a code block. * @param as Actor structure * @param bRunScript Flag for whether to run actor's script for the scene */ void StartActor(const T1_ACTOR_STRUC *as, bool bRunScript) { SCNHANDLE hActorId = FROM_32(as->hActorId); // Zero-out many things actorInfo[hActorId - 1].bHidden = false; actorInfo[hActorId - 1].completed = false; actorInfo[hActorId - 1].x = 0; actorInfo[hActorId - 1].y = 0; actorInfo[hActorId - 1].presReel = NULL; actorInfo[hActorId - 1].presFilm = 0; actorInfo[hActorId - 1].presObj = NULL; // Store current scene's parameters for this actor actorInfo[hActorId - 1].mtype = FROM_32(as->masking); actorInfo[hActorId - 1].actorCode = FROM_32(as->hActorCode); // Run actor's script for this scene if (bRunScript) { if (bActorsOn) actorInfo[hActorId - 1].bAlive = true; if (actorInfo[hActorId - 1].bAlive && FROM_32(as->hActorCode)) ActorEvent(hActorId, STARTUP, PLR_NOEVENT); } }
/** * 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); } }
/** * Returns the length of one line of a string in pixels. * @param szStr String * @param pFont Which font to use for dimensions */ int StringLengthPix(char *szStr, const FONT *pFont) { int strLen; // accumulated length of string byte c; SCNHANDLE hImg; // while not end of string or end of line for (strLen = 0; (c = *szStr) != EOS_CHAR && c != LF_CHAR; szStr++) { if (g_bMultiByte) { if (c & 0x80) c = ((c & ~0x80) << 8) + *++szStr; } hImg = FROM_32(pFont->fontDef[c]); if (hImg) { // there is a IMAGE for this character const IMAGE *pChar = (const IMAGE *)LockMem(hImg); // add width of font bitmap strLen += FROM_16(pChar->imgWidth); } else // use width of space character strLen += FROM_32(pFont->spaceSize); // finally add the inter-character spacing strLen += FROM_32(pFont->xSpacing); } // return length of line in pixels - minus inter-char spacing for last character strLen -= FROM_32(pFont->xSpacing); return (strLen > 0) ? strLen : 0; }
/** * Given the scene background film, extracts the palette handle for * everything else's use, then starts a display process for each reel * in the film. * @param hFilm Scene background film */ void StartupBackground(CORO_PARAM, SCNHANDLE hFilm) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); const FILM *pfilm; IMAGE *pim; g_hBackground = hFilm; // Save handle in case of Save_Scene() pim = GetImageFromFilm(hFilm, 0, NULL, NULL, &pfilm); SetBackPal(FROM_32(pim->hImgPal)); // Extract the film speed g_BGspeed = ONE_SECOND / FROM_32(pfilm->frate); // Start display process for each reel in the film CoroScheduler.createProcess(PID_REEL, BGmainProcess, &pfilm->reels[0], sizeof(FREEL)); if (TinselV0) { for (uint i = 1; i < FROM_32(pfilm->numreels); ++i) CoroScheduler.createProcess(PID_REEL, BGotherProcess, &pfilm->reels[i], sizeof(FREEL)); } if (g_pBG[0] == NULL) ControlStartOff(); if (TinselV2 && (coroParam != Common::nullContext)) CORO_GIVE_WAY; CORO_END_CODE; }
/** * LoadBasicChunks */ void LoadBasicChunks() { byte *cptr; int numObjects; // Allocate RAM for savescene data InitializeSaveScenes(); // CHUNK_TOTAL_ACTORS seems to be missing in the released version, hard coding a value // TODO: Would be nice to just change 511 to MAX_SAVED_ALIVES cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_TOTAL_ACTORS); RegisterActors((cptr != NULL) ? READ_32(cptr) : 511); // CHUNK_TOTAL_GLOBALS seems to be missing in some versions. // So if it is missing, set a reasonably high value for the number of globals. cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_TOTAL_GLOBALS); RegisterGlobals((cptr != NULL) ? READ_32(cptr) : 512); cptr = FindChunk(INV_OBJ_SCNHANDLE, CHUNK_TOTAL_OBJECTS); numObjects = (cptr != NULL) ? READ_32(cptr) : 0; cptr = FindChunk(INV_OBJ_SCNHANDLE, CHUNK_OBJECTS); // Convert to native endianness INV_OBJECT *io = (INV_OBJECT *)cptr; for (int i = 0; i < numObjects; i++, io++) { io->id = FROM_32(io->id); io->hIconFilm = FROM_32(io->hIconFilm); io->hScript = FROM_32(io->hScript); io->attribute = FROM_32(io->attribute); } RegisterIcons(cptr, numObjects); cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_TOTAL_POLY); // Max polygons are 0 in DW1 Mac (both in the demo and the full version) if (cptr != NULL && *cptr != 0) MaxPolygons(*cptr); if (TinselV2) { // Global processes cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_NUM_PROCESSES); assert(cptr && (*cptr < 100)); int num = *cptr; cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_PROCESSES); assert(!num || cptr); GlobalProcesses(num, cptr); // CdPlay() stuff cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_CDPLAY_HANDLE); assert(cptr); uint32 playHandle = READ_32(cptr); assert(playHandle < 512); SetCdPlayHandle(playHandle); } }
static void MoverProcessHelper(int X, int Y, int id, PMOVER pMover) { const FILM *pfilm; const MULTI_INIT *pmi; const FRAME *pFrame; IMAGE *pim; assert(BgPal()); // Can't start actor without a background palette assert(pMover->walkReels[0][FORWARD]); // Starting actor process without walk reels InitMover(pMover); InitialPathChecks(pMover, X, Y); pfilm = (const FILM *)LockMem(pMover->walkReels[0][FORWARD]); pmi = (const MULTI_INIT *)LockMem(FROM_32(pfilm->reels[0].mobj)); //--- pFrame = (const FRAME *)LockMem(FROM_32(pmi->hMulFrame)); // get pointer to image pim = (IMAGE *)LockMem(READ_32(pFrame)); // handle to image pim->hImgPal = TO_32(BgPal()); //--- pMover->actorObj = MultiInitObject(pmi); /**/ assert(pMover->actorID == id); pMover->actorID = id; // add it to display list MultiInsertObject(GetPlayfieldList(FIELD_WORLD), pMover->actorObj); storeActorReel(id, NULL, 0, pMover->actorObj, 0, 0, 0); InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_32(pfilm->reels[0].script), ONE_SECOND / FROM_32(pfilm->frate)); pMover->stepCount = 0; MultiSetAniXY(pMover->actorObj, pMover->objX, pMover->objY); // If no path, just use first path in the scene if (pMover->hCpath != NOPOLY) SetMoverZ(pMover, pMover->objY, GetPolyZfactor(pMover->hCpath)); else SetMoverZ(pMover, pMover->objY, GetPolyZfactor(FirstPathPoly())); // Make him the right size SetMoverStanding(pMover); //**** if added 18/11/94, am if (X != MAGICX && Y != MAGICY) { HideMover(pMover, 0); // Allows a play to come in before this appears pMover->bHidden = false; // ...but don't stay hidden } pMover->bActive = true; }
/** * Process to fade one palette. * A pointer to a 'FADE' structure must be passed to this process when * it is created. */ static void FadeProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; COLORREF fadeRGB[MAX_COLORS]; // local copy of palette const long *pColMult; // pointer to color multiplier table PALETTE *pPalette; // pointer to palette CORO_END_CONTEXT(_ctx); // get the fade data structure - copied to process when it was created const FADE *pFade = (const FADE *)param; CORO_BEGIN_CODE(_ctx); if (TinselV2) // Note that this palette is being faded FadingPalette(pFade->pPalQ, true); // get pointer to palette - reduce pointer indirection a bit _ctx->pPalette = (PALETTE *)LockMem(FROM_32(pFade->pPalQ->hPal)); for (_ctx->pColMult = pFade->pColorMultTable; *_ctx->pColMult >= 0; _ctx->pColMult++) { // go through all multipliers in table - until a negative entry // fade palette using next multiplier if (TinselV2) FadePalette(_ctx->fadeRGB, pFade->pPalQ->palRGB, pFade->pPalQ->numColors, (uint32) *_ctx->pColMult); else FadePalette(_ctx->fadeRGB, _ctx->pPalette->palRGB, FROM_32(_ctx->pPalette->numColors), (uint32) *_ctx->pColMult); // send new palette to video DAC UpdateDACqueue(pFade->pPalQ->posInDAC, FROM_32(_ctx->pPalette->numColors), _ctx->fadeRGB); // allow time for video DAC to be updated CORO_SLEEP(1); } if (TinselV2) // Note that this palette is being faded FadingPalette(pFade->pPalQ, false); CORO_END_CODE; }
/** * Change which reel is playing for a moving actor. */ void AlterMover(PMOVER pMover, SCNHANDLE film, AR_FUNCTION fn) { const FILM *pfilm; assert(pMover->actorObj); // Altering null moving actor's animation script if (fn == AR_POPREEL) { // Use the saved film film = pMover->hPushedFilm; } if (fn == AR_PUSHREEL) { // Save the one we're replacing pMover->hPushedFilm = (pMover->bSpecReel) ? pMover->hLastFilm : 0; } if (film == 0) { if (pMover->bSpecReel) { // Revert to 'normal' actor SetMoverWalkReel(pMover, pMover->direction, pMover->scale, true); pMover->bSpecReel = false; } } else { // Remember this one in case the actor talks pMover->hLastFilm = film; pfilm = (const FILM *)LockMem(film); assert(pfilm != NULL); InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_32(pfilm->reels[0].script), ONE_SECOND / FROM_32(pfilm->frate)); if (!TinselV2) pMover->stepCount = 0; // If no path, just use first path in the scene if (pMover->hCpath != NOPOLY) SetMoverZ(pMover, pMover->objY, GetPolyZfactor(pMover->hCpath)); else SetMoverZ(pMover, pMover->objY, GetPolyZfactor(FirstPathPoly())); if (fn == AR_WALKREEL) { pMover->bSpecReel = false; pMover->bWalkReel = true; } else { pMover->bSpecReel = true; pMover->bWalkReel = false; #ifdef DEBUG assert(StepAnimScript(&pMover->actorAnim) != ScriptFinished); // Actor reel has finished! #else StepAnimScript(&pMover->actorAnim); // 04/01/95 #endif } // Hang on, we may not want him yet! 04/01/95 if (pMover->bHidden) MultiSetZPosition(pMover->actorObj, -1); } }
/** * Called at the start of each scene. Start each actor with a code block. * @param ah Scene handle * @param numActors Number of actors * @param bRunScript Flag for whether to run actor scene scripts */ void StartTaggedActors(SCNHANDLE ah, int numActors, bool bRunScript) { int i; if (TinselV2) { // Clear it all out for a fresh start memset(taggedActors, 0, sizeof(taggedActors)); numTaggedActors = numActors; } else { // Only actors with code blocks got (x, y) re-initialized, so... for (i = 0; i < NumActors; i++) { actorInfo[i].x = actorInfo[i].y = 0; actorInfo[i].mtype = 0; } } if (!TinselV2) { // Tinsel 1 load variation const T1_ACTOR_STRUC *as = (const T1_ACTOR_STRUC *)LockMem(ah); for (i = 0; i < numActors; i++, as++) { StartActor(as, bRunScript); } } else if (numActors > 0) { // Tinsel 2 load variation const T2_ACTOR_STRUC *as = (T2_ACTOR_STRUC *)LockMem(ah); for (i = 0; i < numActors; i++, as++) { assert(as->hActorCode); // Store current scene's parameters for this tagged actor taggedActors[i].id = FROM_32(as->hActorId); taggedActors[i].hTagText = FROM_32(as->hTagText); taggedActors[i].tagPortionV = FROM_32(as->tagPortionV); taggedActors[i].tagPortionH = FROM_32(as->tagPortionH); taggedActors[i].hActorCode = FROM_32(as->hActorCode); // Run actor's script for this scene if (bRunScript) { // Send in reverse order - they get swapped round in the scheduler ActorEvent(Common::nullContext, taggedActors[i].id, SHOWEVENT, false, 0); ActorEvent(Common::nullContext, taggedActors[i].id, STARTUP, false, 0); } } } }
/** * Runs secondary reels for a scene background */ static void BGotherProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; OBJECT *pObj; ANIM anim; CORO_END_CONTEXT(_ctx); const FREEL *pReel = (const FREEL *)param; const MULTI_INIT *pmi = (const MULTI_INIT *)LockMem(FROM_32(pReel->mobj)); CORO_BEGIN_CODE(_ctx); // Initialize and insert the object, and initialize its script. _ctx->pObj = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_WORLD), _ctx->pObj); InitStepAnimScript(&_ctx->anim, g_pBG[0], FROM_32(pReel->script), g_BGspeed); while (StepAnimScript(&_ctx->anim) != ScriptFinished) CORO_SLEEP(1); CORO_END_CODE; }
/** * Get actor to adopt its appropriate walking reel. */ void SetMoverWalkReel(PMOVER pMover, DIRECTION reel, int scale, bool force) { SCNHANDLE whichReel; const FILM *pfilm; // Kill off any play that may be going on for this actor // and restore the real actor storeActorReel(pMover->actorID, NULL, 0, NULL, 0, 0, 0); UnHideMover(pMover); // Don't do it if using a special walk reel if (pMover->bWalkReel) return; if (force || pMover->scale != scale || pMover->direction != reel) { assert(reel >= 0 && reel <= 3 && scale > 0 && scale <= TOTAL_SCALES); // out of range scale or reel // If scale change and both are regular scales // and there's a scaling reel in the right direction if (pMover->scale != scale && scale <= NUM_MAINSCALES && pMover->scale <= NUM_MAINSCALES && (whichReel = ScalingReel(pMover->actorID, pMover->scale, scale, reel)) != 0) { // error("Cripes"); ; // Use what is now in 'whichReel' } else { whichReel = pMover->walkReels[scale-1][reel]; assert(whichReel); // no reel } pfilm = (const FILM *)LockMem(whichReel); assert(pfilm != NULL); // no film InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_32(pfilm->reels[0].script), 1); // Synchronised walking reels assert(pMover->stepCount >= 0); SkipFrames(&pMover->actorAnim, pMover->stepCount); pMover->scale = scale; pMover->direction = reel; } }
/** * Main text outputting routine. If a object list is specified a * multi-object is created for the whole text and a pointer to the head * of the list is returned. * @param pList Object list to add text to * @param szStr String to output * @param color Color for monochrome text * @param xPos X position of string * @param yPos Y position of string * @param hFont Which font to use * @param mode Mode flags for the string * @param sleepTime Sleep time between each character (if non-zero) */ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color, int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime) { int xJustify; // x position of text after justification int yOffset; // offset to next line of text OBJECT *pFirst; // head of multi-object text list OBJECT *pChar = 0; // object ptr for the character byte c; SCNHANDLE hImg; const IMAGE *pImg; // make sure there is a linked list to add text to assert(pList); // get font pointer const FONT *pFont = (const FONT *)LockMem(hFont); // init head of text list pFirst = NULL; // get image for capital W assert(pFont->fontDef[(int)'W']); pImg = (const IMAGE *)LockMem(FROM_32(pFont->fontDef[(int)'W'])); // get height of capital W for offset to next line yOffset = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; while (*szStr) { // x justify the text according to the mode flags xJustify = JustifyText(szStr, xPos, pFont, mode); // repeat until end of string or end of line while ((c = *szStr) != EOS_CHAR && c != LF_CHAR) { if (g_bMultiByte) { if (c & 0x80) c = ((c & ~0x80) << 8) + *++szStr; } hImg = FROM_32(pFont->fontDef[c]); if (hImg == 0) { // no image for this character // add font spacing for a space character xJustify += FROM_32(pFont->spaceSize); } else { // printable character int aniX, aniY; // char image animation offsets OBJ_INIT oi; oi.hObjImg = FROM_32(pFont->fontInit.hObjImg); oi.objFlags = FROM_32(pFont->fontInit.objFlags); oi.objID = FROM_32(pFont->fontInit.objID); oi.objX = FROM_32(pFont->fontInit.objX); oi.objY = FROM_32(pFont->fontInit.objY); oi.objZ = FROM_32(pFont->fontInit.objZ); // allocate and init a character object if (pFirst == NULL) // first time - init head of list pFirst = pChar = InitObject(&oi); // FIXME: endian issue using fontInit!!! else // chain to multi-char list pChar = pChar->pSlave = InitObject(&oi); // FIXME: endian issue using fontInit!!! // convert image handle to pointer pImg = (const IMAGE *)LockMem(hImg); // fill in character object pChar->hImg = hImg; // image def pChar->width = FROM_16(pImg->imgWidth); // width of chars bitmap pChar->height = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; // height of chars bitmap pChar->hBits = FROM_32(pImg->hImgBits); // bitmap // check for absolute positioning if (mode & TXT_ABSOLUTE) pChar->flags |= DMA_ABS; // set characters color - only effective for mono fonts pChar->constant = color; // get Y animation offset GetAniOffset(hImg, pChar->flags, &aniX, &aniY); // set x position - ignore animation point pChar->xPos = intToFrac(xJustify); // set y position - adjust for animation point pChar->yPos = intToFrac(yPos - aniY); if (mode & TXT_SHADOW) { // we want to shadow the character OBJECT *pShad; // allocate a object for the shadow and chain to multi-char list pShad = pChar->pSlave = AllocObject(); // copy the character for a shadow CopyObject(pShad, pChar); // add shadow offsets to characters position pShad->xPos += intToFrac(FROM_32(pFont->xShadow)); pShad->yPos += intToFrac(FROM_32(pFont->yShadow)); // shadow is behind the character pShad->zPos--; // shadow is always mono pShad->flags = DMA_CNZ | DMA_CHANGED; // check for absolute positioning if (mode & TXT_ABSOLUTE) pShad->flags |= DMA_ABS; // shadow always uses first palette entry // should really alloc a palette here also ???? pShad->constant = 1; // add shadow to object list InsertObject(pList, pShad); } // add character to object list InsertObject(pList, pChar); // move to end of list if (pChar->pSlave) pChar = pChar->pSlave; // add character spacing xJustify += FROM_16(pImg->imgWidth); } // finally add the inter-character spacing xJustify += FROM_32(pFont->xSpacing); // next character in string ++szStr; } // adjust the text y position and add the inter-line spacing yPos += yOffset + FROM_32(pFont->ySpacing); // check for newline if (c == LF_CHAR) // next character in string ++szStr; } // return head of list return pFirst; }
/** * Tinsel 2 Moving actor process * - 1 per moving actor in current scene. */ void T2MoverProcess(CORO_PARAM, const void *param) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); // Get the co-ordinates - copied to process when it was created const MAINIT *rpos = (const MAINIT *)param; PMOVER pMover = rpos->pMover; int i; FILM *pFilm; PMULTI_INIT pmi; CORO_BEGIN_CODE(_ctx); for (i = 0; i < TOTAL_SCALES; i++) { if (pMover->walkReels[i][FORWARD]) break; } assert(i < TOTAL_SCALES); InitMover(pMover); InitialPathChecks(pMover, rpos->X, rpos->Y); pFilm = (FILM *)LockMem(pMover->walkReels[i][FORWARD]); // Any old reel pmi = (PMULTI_INIT)LockMem(FROM_32(pFilm->reels[0].mobj)); // Poke in the background palette PokeInPalette(pmi); pMover->actorObj = MultiInitObject(pmi); // FIXME: This is what the original did. A bug, perhaps? // pMover->actorID = pMover->actorID; pMover->bActive = true; // add it to display list MultiInsertObject( GetPlayfieldList(FIELD_WORLD), pMover->actorObj ); InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, pFilm->reels[0].script, ONE_SECOND/pFilm->frate); pMover->stepCount = 0; MultiSetAniXY(pMover->actorObj, pMover->objX, pMover->objY); // If no path, just use first path in the scene if (pMover->hCpath != NOPOLY) SetMoverZ(pMover, pMover->objY, GetPolyZfactor(pMover->hCpath)); else SetMoverZ(pMover, pMover->objY, GetPolyZfactor(FirstPathPoly())); // Make him the right size SetMoverStanding(pMover); HideMover(pMover); // Allows a play to come in before this appears pMover->bHidden = false; // ...but don't stay hidden for (;;) { if (pMover->bSpecReel) { if (!pMover->bHidden) StepAnimScript(&pMover->actorAnim); } else DoMoveActor(pMover); CheckBrightness(pMover); CORO_SLEEP(1); } CORO_END_CODE; }
bool PCMMusicPlayer::getNextChunk() { MusicSegment *musicSegments; int32 *script, *scriptBuffer; int id; int snum; uint32 sampleOffset, sampleLength, sampleCLength; Common::File file; byte *buffer; Common::SeekableReadStream *sampleStream; switch (_state) { case S_NEW: case S_NEXT: _forcePlay = false; script = scriptBuffer = (int32 *)LockMem(_hScript); // Set parameters for this chunk of music id = _scriptNum; while (id--) script = scriptBuffer + READ_32(script); snum = FROM_32(script[_scriptIndex++]); if (snum == MUSIC_JUMP || snum == MUSIC_END) { // Let usual code sort it out! _scriptIndex--; // Undo increment _forcePlay = true; // Force a Play _state = S_END1; // 'Goto' S_END1 break; } musicSegments = (MusicSegment *) LockMem(_hSegment); assert(FROM_32(musicSegments[snum].numChannels) == 1); assert(FROM_32(musicSegments[snum].bitsPerSample) == 16); sampleOffset = FROM_32(musicSegments[snum].sampleOffset); sampleLength = FROM_32(musicSegments[snum].sampleLength); sampleCLength = (((sampleLength + 63) & ~63)*33)/64; if (!file.open(_filename)) error(CANNOT_FIND_FILE, _filename.c_str()); file.seek(sampleOffset); if (file.eos() || file.err() || (uint32)file.pos() != sampleOffset) error(FILE_IS_CORRUPT, _filename.c_str()); buffer = (byte *) malloc(sampleCLength); assert(buffer); // read all of the sample if (file.read(buffer, sampleCLength) != sampleCLength) error(FILE_IS_CORRUPT, _filename.c_str()); debugC(DEBUG_DETAILED, kTinselDebugMusic, "Creating ADPCM music chunk with size %d, " "offset %d (script %d.%d)", sampleCLength, sampleOffset, _scriptNum, _scriptIndex - 1); sampleStream = new Common::MemoryReadStream(buffer, sampleCLength, DisposeAfterUse::YES); delete _curChunk; _curChunk = new Tinsel8_ADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength, 22050, 1, 32); _state = S_MID; return true; case S_END1: debugC(DEBUG_DETAILED, kTinselDebugMusic, "Music reached state S_END1 (script %d.%d)", _scriptNum, _scriptIndex); script = scriptBuffer = (int32 *) LockMem(_hScript); id = _scriptNum; while (id--) script = scriptBuffer + READ_32(script); snum = FROM_32(script[_scriptIndex]); if (snum == MUSIC_END) { _state = S_END2; } else { if (snum == MUSIC_JUMP) _scriptIndex = FROM_32(script[_scriptIndex+1]); _state = _forcePlay ? S_NEW : S_NEXT; _forcePlay = false; } return true; case S_END2: debugC(DEBUG_DETAILED, kTinselDebugMusic, "Music reached state S_END2 (script %d.%d)", _scriptNum, _scriptIndex); _silenceSamples = 11025; // Half a second of silence return true; case S_END3: debugC(DEBUG_DETAILED, kTinselDebugMusic, "Music reached state S_END3 (script %d.%d)", _scriptNum, _scriptIndex); stop(); _state = S_IDLE; return false; case S_IDLE: return false; default: break; } return true; }
/** * Run main animation that comprises the scene background. */ static void BGmainProcess(CORO_PARAM, const void *param) { // COROUTINE CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); const FILM *pFilm; const FREEL *pReel; const MULTI_INIT *pmi; // get the stuff copied to process when it was created if (g_pBG[0] == NULL) { /*** At start of scene ***/ if (!TinselV2) { pReel = (const FREEL *)param; // Get the MULTI_INIT structure pmi = (const MULTI_INIT *)LockMem(FROM_32(pReel->mobj)); // Initialize and insert the object, and initialize its script. g_pBG[0] = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_WORLD), g_pBG[0]); InitStepAnimScript(&g_thisAnim[0], g_pBG[0], FROM_32(pReel->script), g_BGspeed); g_bgReels = 1; } else { /*** At start of scene ***/ pFilm = (const FILM *)LockMem(g_hBackground); g_bgReels = FROM_32(pFilm->numreels); int i; for (i = 0; i < g_bgReels; i++) { // Get the MULTI_INIT structure pmi = (PMULTI_INIT) LockMem(FROM_32(pFilm->reels[i].mobj)); // Initialize and insert the object, and initialize its script. g_pBG[i] = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_WORLD), g_pBG[i]); MultiSetZPosition(g_pBG[i], 0); InitStepAnimScript(&g_thisAnim[i], g_pBG[i], FROM_32(pFilm->reels[i].script), g_BGspeed); if (i > 0) g_pBG[i-1]->pSlave = g_pBG[i]; } } if (g_bDoFadeIn) { FadeInFast(NULL); g_bDoFadeIn = false; } else if (TinselV2) PokeInTagColor(); for (;;) { for (int i = 0; i < g_bgReels; i++) { if (StepAnimScript(&g_thisAnim[i]) == ScriptFinished) error("Background animation has finished"); } CORO_SLEEP(1); } } else { // New background during scene if (!TinselV2) { pReel = (const FREEL *)param; InitStepAnimScript(&g_thisAnim[0], g_pBG[0], FROM_32(pReel->script), g_BGspeed); StepAnimScript(&g_thisAnim[0]); } else { pFilm = (const FILM *)LockMem(g_hBackground); assert(g_bgReels == (int32)FROM_32(pFilm->numreels)); // Just re-initialize the scripts. for (int i = 0; i < g_bgReels; i++) { InitStepAnimScript(&g_thisAnim[i], g_pBG[i], pFilm->reels[i].script, g_BGspeed); StepAnimScript(&g_thisAnim[i]); } } } CORO_END_CODE; }