示例#1
0
/**
 * 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;
}
示例#2
0
/**
 * Run a scene process with the given event.
 */
void SceneProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait, int myEscape,
						bool *result) {
	uint32 i;		// Loop counter
	if (result) *result = false;

	CORO_BEGIN_CONTEXT;
		PROCESS_STRUC *pStruc;
		PPROCESS pProc;
		PINT_CONTEXT pic;
	CORO_END_CONTEXT(_ctx);

	CORO_BEGIN_CODE(_ctx);

	_ctx->pStruc = (PROCESS_STRUC *)LockMem(hSceneProcess);
	for (i = 0; i < numSceneProcess; i++) {
		if (FROM_LE_32(_ctx->pStruc[i].processId) == procID) {
			assert(_ctx->pStruc[i].hProcessCode);		// Must have some code to run

			_ctx->pic = InitInterpretContext(GS_PROCESS,
				FROM_LE_32(_ctx->pStruc[i].hProcessCode),
				event,
				NOPOLY,			// No polygon
				0,			// No actor
				NULL,			// No object
				myEscape);
			if (_ctx->pic == NULL)
				return;

			_ctx->pProc = g_scheduler->createProcess(PID_PROCESS + i, ProcessTinselProcess,
				&_ctx->pic, sizeof(_ctx->pic));
			AttachInterpret(_ctx->pic, _ctx->pProc);
			break;
		}
	}

	if (i == numSceneProcess)
		return;

	if (bWait) {
		CORO_INVOKE_2(WaitInterpret, _ctx->pProc, result);
	}

	CORO_END_CODE;
}
示例#3
0
/**
 * 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;
	}
}
示例#4
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_LE_32(pReel->mobj));

	CORO_BEGIN_CODE(_ctx);

	// Initialise and insert the object, and initialise its script.
	_ctx->pObj = MultiInitObject(pmi);
	MultiInsertObject(GetPlayfieldList(FIELD_WORLD), _ctx->pObj);

	InitStepAnimScript(&_ctx->anim, pBG[0], FROM_LE_32(pReel->script), BGspeed);

	while (StepAnimScript(&_ctx->anim) != ScriptFinished)
		CORO_SLEEP(1);

	CORO_END_CODE;
}
示例#5
0
/**
 * About to jump or end
 * @param pAnim			Animation data structure
 */
bool AboutToJumpOrEnd(PANIM pAnim) {
	if (pAnim->aniDelta == 1) {
		// get a pointer to the script
		ANI_SCRIPT *pAni = (ANI_SCRIPT *)LockMem(pAnim->hScript);
		int	zzz = pAnim->scriptIndex;

		for (;;) {
			// repeat until a real image
			switch (FROM_LE_32(pAni[zzz].op)) {
			case ANI_END:		// end of animation script
			case ANI_JUMP:		// do animation jump
				return true;

			case ANI_HFLIP:		// flip animated object horizontally
			case ANI_VFLIP:		// flip animated object vertically
			case ANI_HVFLIP:	// flip animated object in both directions
				zzz++;
				break;

			case ANI_ADJUSTX:	// adjust animated object x animation point
			case ANI_ADJUSTY:	// adjust animated object y animation point
				zzz += 2;
				break;

			case ANI_ADJUSTXY:	// adjust animated object x & y animation points
				zzz += 3;
				break;

			case ANI_HIDE:		// hide animated object
			default:		// must be an actual animation frame handle
				return false;
			}
		}
	}

	return false;
}
示例#6
0
/**
 * 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 (pBG[0] == NULL) {
		/*** At start of scene ***/

		if (!TinselV2) {
			pReel = (const FREEL *)param;

			// Get the MULTI_INIT structure
			pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pReel->mobj));

			// Initialise and insert the object, and initialise its script.
			pBG[0] = MultiInitObject(pmi);
			MultiInsertObject(GetPlayfieldList(FIELD_WORLD), pBG[0]);
			InitStepAnimScript(&thisAnim[0], pBG[0], FROM_LE_32(pReel->script), BGspeed);
			bgReels = 1;
		} else {
			/*** At start of scene ***/
			pFilm = (const FILM *)LockMem(hBackground);
			bgReels = FROM_LE_32(pFilm->numreels);

			int i;
			for (i = 0; i < bgReels; i++) {
				// Get the MULTI_INIT structure
				pmi = (PMULTI_INIT) LockMem(FROM_LE_32(pFilm->reels[i].mobj));

				// Initialise and insert the object, and initialise its script.
				pBG[i] = MultiInitObject(pmi);
				MultiInsertObject(GetPlayfieldList(FIELD_WORLD), pBG[i]);
				MultiSetZPosition(pBG[i], 0);
				InitStepAnimScript(&thisAnim[i], pBG[i], FROM_LE_32(pFilm->reels[i].script), BGspeed);

				if (i > 0)
					pBG[i-1]->pSlave = pBG[i];
			}
		}

		if (bDoFadeIn) {
			FadeInFast(NULL);
			bDoFadeIn = false;
		} else if (TinselV2)
			PokeInTagColor();

		for (;;) {
			for (int i = 0; i < bgReels; i++) {
				if (StepAnimScript(&thisAnim[i]) == ScriptFinished)
					error("Background animation has finished");
			}

			CORO_SLEEP(1);
		}
	} else {
		// New background during scene
		if (!TinselV2) {
			pReel = (const FREEL *)param;
			InitStepAnimScript(&thisAnim[0], pBG[0], FROM_LE_32(pReel->script), BGspeed);
			StepAnimScript(&thisAnim[0]);
		} else {
			pFilm = (const FILM *)LockMem(hBackground);
			assert(bgReels == (int32)FROM_LE_32(pFilm->numreels));

			// Just re-initialise the scripts.
			for (int i = 0; i < bgReels; i++) {
				InitStepAnimScript(&thisAnim[i], pBG[i], pFilm->reels[i].script, BGspeed);
				StepAnimScript(&thisAnim[i]);
			}
		}
	}

	CORO_END_CODE;
}
示例#7
0
/**
 * Advance to next frame routine.
 * @param pAnim			Animation data structure
 */
SCRIPTSTATE DoNextFrame(ANIM *pAnim) {
	// get a pointer to the script
	const ANI_SCRIPT *pAni = (const ANI_SCRIPT *)LockMem(pAnim->hScript);

	while (1) {	// repeat until a real image
		debugC(DEBUG_DETAILED, kTinselDebugAnimations,
		"DoNextFrame %ph index=%d, op=%xh", (byte *)pAnim, pAnim->scriptIndex,
		FROM_LE_32(pAni[pAnim->scriptIndex].op));

		switch ((int32)FROM_LE_32(pAni[pAnim->scriptIndex].op)) {
		case ANI_END:	// end of animation script

			// move to next opcode
			pAnim->scriptIndex++;

			// indicate script has finished
			return ScriptFinished;

		case ANI_JUMP:	// do animation jump

			// move to jump address
			pAnim->scriptIndex++;

			// jump to new frame position
			pAnim->scriptIndex += (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op);

			// go fetch a real image
			break;

		case ANI_HFLIP:	// flip animated object horizontally

			// next opcode
			pAnim->scriptIndex++;

			MultiHorizontalFlip(pAnim->pObject);

			// go fetch a real image
			break;

		case ANI_VFLIP:	// flip animated object vertically

			// next opcode
			pAnim->scriptIndex++;

			MultiVerticalFlip(pAnim->pObject);

			// go fetch a real image
			break;
		case ANI_HVFLIP:	// flip animated object in both directions

			// next opcode
			pAnim->scriptIndex++;

			MultiHorizontalFlip(pAnim->pObject);
			MultiVerticalFlip(pAnim->pObject);

			// go fetch a real image
			break;

		case ANI_ADJUSTX:	// adjust animated object x animation point

			// move to x adjustment operand
			pAnim->scriptIndex++;

			MultiAdjustXY(pAnim->pObject, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op), 0);

			// next opcode
			pAnim->scriptIndex++;

			// go fetch a real image
			break;

		case ANI_ADJUSTY:	// adjust animated object y animation point

			// move to y adjustment operand
			pAnim->scriptIndex++;

			MultiAdjustXY(pAnim->pObject, 0, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op));

			// next opcode
			pAnim->scriptIndex++;

			// go fetch a real image
			break;

		case ANI_ADJUSTXY:	// adjust animated object x & y animation points
		{
			int x, y;

			// move to x adjustment operand
			pAnim->scriptIndex++;
			x = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op);

			// move to y adjustment operand
			pAnim->scriptIndex++;
			y = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op);

			MultiAdjustXY(pAnim->pObject, x, y);

			// next opcode
			pAnim->scriptIndex++;

			// go fetch a real image
			break;
		}

		case ANI_NOSLEEP:	// do not sleep for this frame

			// next opcode
			pAnim->scriptIndex++;

			// indicate not to sleep
			return ScriptNoSleep;

		case ANI_CALL:		// call routine

			// move to function address
			pAnim->scriptIndex++;

			// make function call

			// REMOVED BUGGY CODE
			// pFunc is a function pointer that's part of a union and is assumed to be 32-bits.
			// There is no known place where a function pointer is stored inside the animation
			// scripts, something which wouldn't have worked anyway. Having played through the
			// entire game, there hasn't been any occurence of this case, so just error out here
			// in case we missed something (highly unlikely though)
			error("ANI_CALL opcode encountered! Please report this error to the ScummVM team");
			//(*pAni[pAnim->scriptIndex].pFunc)(pAnim);
			return ScriptSleep;	// for compilers that don't support NORETURN

#if 0
			// next opcode
			pAnim->scriptIndex++;

			// go fetch a real image
			break;
#endif

		case ANI_HIDE:		// hide animated object

			MultiHideObject(pAnim->pObject);

			// next opcode
			pAnim->scriptIndex++;

			// dont skip a sleep
			return ScriptSleep;

		default:	// must be an actual animation frame handle

			// set objects new animation frame
			pAnim->pObject->hShape = FROM_LE_32(pAni[pAnim->scriptIndex].hFrame);

			// re-shape the object
			MultiReshape(pAnim->pObject);

			// next opcode
			pAnim->scriptIndex++;

			// dont skip a sleep
			return ScriptSleep;
		}
	}
}
示例#8
0
/**
 * Skip the specified number of frames.
 * @param pAnim			Animation data structure
 * @param numFrames		Number of frames to skip
 */
void SkipFrames(ANIM *pAnim, int numFrames) {
	// get a pointer to the script
	const ANI_SCRIPT *pAni = (const ANI_SCRIPT *)LockMem(pAnim->hScript);

	if (!TinselV2 && (numFrames <= 0))
		// do nothing
		return;

	while (1) {	// repeat until a real image

		switch ((int32)FROM_LE_32(pAni[pAnim->scriptIndex].op)) {
		case ANI_END:	// end of animation script
			// going off the end is probably a error, but only in Tinsel 1
			if (!TinselV2)
				error("SkipFrames(): formally 'assert(0)!'");
			return;

		case ANI_JUMP:	// do animation jump

			// move to jump address
			pAnim->scriptIndex++;

			// jump to new frame position
			pAnim->scriptIndex += (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op);

			if (TinselV2)
				// Done if skip to jump
				return;
			break;

		case ANI_HFLIP:	// flip animated object horizontally

			// next opcode
			pAnim->scriptIndex++;

			MultiHorizontalFlip(pAnim->pObject);
			break;

		case ANI_VFLIP:	// flip animated object vertically

			// next opcode
			pAnim->scriptIndex++;

			MultiVerticalFlip(pAnim->pObject);
			break;

		case ANI_HVFLIP:	// flip animated object in both directions

			// next opcode
			pAnim->scriptIndex++;

			MultiHorizontalFlip(pAnim->pObject);
			MultiVerticalFlip(pAnim->pObject);
			break;

		case ANI_ADJUSTX:	// adjust animated object x animation point

			// move to x adjustment operand
			pAnim->scriptIndex++;

			MultiAdjustXY(pAnim->pObject, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op), 0);

			// next opcode
			pAnim->scriptIndex++;
			break;

		case ANI_ADJUSTY:	// adjust animated object y animation point

			// move to y adjustment operand
			pAnim->scriptIndex++;

			MultiAdjustXY(pAnim->pObject, 0, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op));

			// next opcode
			pAnim->scriptIndex++;
			break;

		case ANI_ADJUSTXY:	// adjust animated object x & y animation points
		{
			int x, y;

			// move to x adjustment operand
			pAnim->scriptIndex++;
			x = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op);

			// move to y adjustment operand
			pAnim->scriptIndex++;
			y = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op);

			MultiAdjustXY(pAnim->pObject, x, y);

			// next opcode
			pAnim->scriptIndex++;

			break;
		}

		case ANI_NOSLEEP:	// do not sleep for this frame

			// next opcode
			pAnim->scriptIndex++;
			break;

		case ANI_CALL:		// call routine

			// skip function address
			pAnim->scriptIndex += 2;
			break;

		case ANI_HIDE:		// hide animated object

			// next opcode
			pAnim->scriptIndex++;
			break;

		default:	// must be an actual animation frame handle

			// one less frame
			if (numFrames == 0)
				return;

			if (numFrames == -1 || numFrames-- > 0) {
				// next opcode
				pAnim->scriptIndex++;
			} else {
				// set objects new animation frame
				pAnim->pObject->hShape = FROM_LE_32(pAni[pAnim->scriptIndex].hFrame);

				// re-shape the object
				MultiReshape(pAnim->pObject);

				// we have skipped to the correct place
				return;
			}
			break;
		}
	}
}
示例#9
0
/**
 * Initialise a object using a OBJ_INIT structure to supply parameters.
 * @param pInitTbl			Pointer to object initialisation table
 */
OBJECT *InitObject(const OBJ_INIT *pInitTbl) {
	// allocate a new object
	OBJECT *pObj = AllocObject();

	// make sure object created
	assert(pObj != NULL);

	// set objects shape
	pObj->hImg = pInitTbl->hObjImg;

	// set objects ID
	pObj->oid = pInitTbl->objID;

	// set objects flags
	pObj->flags = DMA_CHANGED | pInitTbl->objFlags;

	// set objects Z position
	pObj->zPos = pInitTbl->objZ;

	// get pointer to image
	if (pInitTbl->hObjImg) {
		int aniX, aniY;		// objects animation offsets
		PALQ *pPalQ = NULL;	// palette queue pointer
		const IMAGE *pImg = (const IMAGE *)LockMem(pInitTbl->hObjImg);	// handle to image

		if (pImg->hImgPal) {
			// allocate a palette for this object
			pPalQ = AllocPalette(FROM_LE_32(pImg->hImgPal));

			// make sure palette allocated
			assert(pPalQ != NULL);
		}

		// assign palette to object
		pObj->pPal = pPalQ;

		// set objects size
		pObj->width  = FROM_LE_16(pImg->imgWidth);
		pObj->height = FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK;
		pObj->flags &= ~C16_FLAG_MASK;
		pObj->flags |= FROM_LE_16(pImg->imgHeight) & C16_FLAG_MASK;

		// set objects bitmap definition
		pObj->hBits = FROM_LE_32(pImg->hImgBits);

		// get animation offset of object
		GetAniOffset(pObj->hImg, pInitTbl->objFlags, &aniX, &aniY);

		// set objects X position - subtract ani offset
		pObj->xPos = intToFrac(pInitTbl->objX - aniX);

		// set objects Y position - subtract ani offset
		pObj->yPos = intToFrac(pInitTbl->objY - aniY);
	} else {	// no image handle - null image

		// set objects X position
		pObj->xPos = intToFrac(pInitTbl->objX);

		// set objects Y position
		pObj->yPos = intToFrac(pInitTbl->objY);
	}

	// return new object
	return pObj;
}
示例#10
0
文件: text.cpp 项目: rayzer86/scummvm
/**
 * 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;
}
示例#11
0
static void LoadScene(SCNHANDLE scene, int entry) {
	uint	i;
	TP_INIT init;
	const SCENE_STRUC	*ss;
	const ENTRANCE_STRUC	*es;

	// Scene handle
	SceneHandle = scene;		// Save scene handle in case of Save_Scene()
	LockMem(SceneHandle);		// Make sure scene is loaded
	LockScene(SceneHandle);		// Prevent current scene from being discarded

	if (TinselV2) {
		// CdPlay() stuff
		byte *cptr = FindChunk(scene, CHUNK_CDPLAY_FILENUM);
		assert(cptr);
		i = READ_LE_UINT32(cptr);
		assert(i < 512);
		cptr = FindChunk(scene, CHUNK_CDPLAY_FILENAME);
		assert(cptr);
		SetCdPlaySceneDetails(i, (const char *)cptr);
	}

	// Find scene structure
	ss = GetSceneStruc(FindChunk(scene, CHUNK_SCENE));
	assert(ss != NULL);

	if (TinselV2) {
		// Handle to scene description
		newestScene = FROM_LE_32(ss->hSceneDesc);

		// Music stuff
		char *cptr = (char *)FindChunk(scene, CHUNK_MUSIC_FILENAME);
		assert(cptr);
		_vm->_pcmMusic->setMusicSceneDetails(FROM_LE_32(ss->hMusicScript),
			FROM_LE_32(ss->hMusicSegment), cptr);
	}

	if (entry == NO_ENTRY_NUM) {
		// Restoring scene

		// Initialise all the polygons for this scene
		InitPolygons(FROM_LE_32(ss->hPoly), FROM_LE_32(ss->numPoly), true);

		// Initialise the actors for this scene
		StartTaggedActors(FROM_LE_32(ss->hTaggedActor), FROM_LE_32(ss->numTaggedActor), false);

		if (TinselV2)
			// Returning from cutscene
			SendSceneTinselProcess(RESTORE);

	} else {
		// Genuine new scene

		// Initialise all the polygons for this scene
		InitPolygons(FROM_LE_32(ss->hPoly), FROM_LE_32(ss->numPoly), false);

		// Initialise the actors for this scene
		StartTaggedActors(FROM_LE_32(ss->hTaggedActor), FROM_LE_32(ss->numTaggedActor), true);

		// Run the appropriate entrance code (if any)
		es = (const ENTRANCE_STRUC *)LockMem(FROM_LE_32(ss->hEntrance));
		for (i = 0; i < FROM_LE_32(ss->numEntrance); i++) {
			if (FROM_LE_32(es->eNumber) == (uint)entry) {
				if (es->hScript) {
					init.event = STARTUP;
					init.hTinselCode = es->hScript;

					g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init));
				}
				break;
			}

			// Move to next entrance
			if (TinselV2)
				++es;
			else
				es = (const ENTRANCE_STRUC *)((const byte *)es + 8);

		}

		if (i == FROM_LE_32(ss->numEntrance))
			error("Non-existant scene entry number");

		if (ss->hSceneScript) {
			init.event = STARTUP;
			init.hTinselCode = ss->hSceneScript;

			g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init));
		}
	}

	// Default refer type
	SetDefaultRefer(FROM_LE_32(ss->defRefer));

	// Scene's processes
	SceneProcesses(FROM_LE_32(ss->numProcess), FROM_LE_32(ss->hProcess));
}
示例#12
0
/**
 * 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;
}
示例#13
0
文件: music.cpp 项目: Cruel/scummvm
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;
}