示例#1
0
/**
 * Allocate and initialize an interpret context.
 * Called from a process prior to Interpret().
 * @param gsort			which sort of code
 * @param hCode			Handle to code to execute
 * @param event			Causal event
 * @param hpoly			Associated polygon (if any)
 * @param actorId		Associated actor (if any)
 * @param pinvo			Associated inventory object
 */
INT_CONTEXT *InitInterpretContext(GSORT gsort, SCNHANDLE hCode,	TINSEL_EVENT event,
		HPOLYGON hpoly, int actorid, INV_OBJECT *pinvo, int myEscape) {
	INT_CONTEXT *ic;

	ic = AllocateInterpretContext(gsort);

	// Previously parameters to Interpret()
	ic->hCode = hCode;
	LockCode(ic);
	ic->event = event;
	ic->hPoly = hpoly;
	ic->idActor = actorid;
	ic->pinvo = pinvo;

	// Previously local variables in Interpret()
	ic->bHalt = false;		// set to exit interpeter
	ic->escOn = myEscape > 0;
	ic->myEscape = myEscape;
	ic->sp = 0;
	ic->bp = ic->sp + 1;
	ic->ip = 0;			// start of code

	ic->resumeState = RES_NOT;

	return ic;
}
示例#2
0
/**
 * Allocate and initialize an interpret context with restored data.
 */
INT_CONTEXT *RestoreInterpretContext(INT_CONTEXT *ric) {
	INT_CONTEXT *ic;

	ic = AllocateInterpretContext(GS_NONE);	// Sort will soon be overridden

	memcpy(ic, ric, sizeof(INT_CONTEXT));
	ic->pProc = g_scheduler->getCurrentProcess();
	ic->resumeState = RES_1;

	LockCode(ic);

	return ic;
}
示例#3
0
//-----------------------------------------------------------------------------
//!
//-----------------------------------------------------------------------------
void tSiriusController::CreateSiriusActions()
{
    // Select from all available channels action
    m_pSelectFromAllAction = new tAction(QIcon(), tr("Subscribed", "Sirius subscribed channels menu selection"), this );
    Connect( m_pSelectFromAllAction, SIGNAL( triggered() ), this, SLOT( SelectChannels() ), Qt::QueuedConnection );

    // Select from favorites only action
    m_pSelectFromFavoritesAction = new tAction(QIcon(), tr("Favorites", "Sirius user favorite channels menu selection"), this );
    Connect( m_pSelectFromFavoritesAction, SIGNAL( triggered() ), this, SLOT(SelectFavoriteChannels() ) );

    RefreshFavoriteChannels(tAudioSettings::Instance()->Favorites());

    // Channels status action
    m_pAllChannelStatusAction = new tAction(QIcon(), tr("All", "Sirius all channels menu selection"), this );
    Connect( m_pAllChannelStatusAction, SIGNAL( triggered() ), this, SLOT( AllChannelStatus() ) );

    // Select by category action
    m_pCategoryAction = new tAction( tr( "By category", "Sirius channel categories menu selection" ), this );
    Connect( m_pCategoryAction, SIGNAL( triggered() ), this, SLOT( SelectCategory() )) ; 

    // Channels SubMenu 
    m_pChannelsSubMenuAction = new tAction( tr( "Channels", "Sirius channel menu selection" ), this );
    m_pChannelsSubMenuAction->AppendSubAction( m_pSelectFromAllAction );
    m_pChannelsSubMenuAction->AppendSubAction( m_pSelectFromFavoritesAction );
    m_pChannelsSubMenuAction->AppendSubAction( m_pAllChannelStatusAction );
    m_pChannelsSubMenuAction->AppendSubAction( m_pCategoryAction );
    //when channels is selected we need to know this so we can refresh lists and whether a menu selection is grayed out or not
    Connect( m_pChannelsSubMenuAction, SIGNAL( triggered() ), this, SLOT( ChannelsSubmenuSelected() ) );
    //the above works for Cougar, but is not working for HDS, so in contextMenuEvent I update the channels menu
    m_MenuActionList << m_pChannelsSubMenuAction;

    m_pOptionsAction = new tAction( tr( "Options" ), this );

    // Lock code action
    m_pLockCodeAction = new tAction( tr( "Change lock code" ), this );
    Connect( m_pLockCodeAction, SIGNAL( triggered() ), this, SLOT( LockCode() ), Qt::QueuedConnection );
    m_MenuActionList << m_pLockCodeAction;

    // Lock current channel action
    m_pLockChannelAction = new tAction( tr("Lock channel"), this );
    m_pLockChannelAction->setCheckable( true );
    Connect( m_pLockChannelAction, SIGNAL( toggled( bool ) ), this, SLOT( LockChannel( bool ) ) );
    m_MenuActionList << m_pLockChannelAction;

}
示例#4
0
/**
 * Interprets the PCODE instructions in the code array.
 */
void Interpret(CORO_PARAM, INT_CONTEXT *ic) {
	do {
		int tmp, tmp2;
		int ip = ic->ip;
		const WorkaroundEntry *wkEntry = ic->fragmentPtr;

		if (wkEntry == NULL) {
			// Check to see if a workaround fragment needs to be executed
			for (wkEntry = workaroundList; wkEntry->script != NULL; ++wkEntry) {
				if ((wkEntry->version == TinselVersion) &&
					(wkEntry->hCode == ic->hCode) &&
					(wkEntry->ip == ip) &&
					(!TinselV1 || (wkEntry->scnFlag == ((_vm->getFeatures() & GF_SCNFILES) != 0)))) {
					// Point to start of workaround fragment
					ip = 0;
					break;
				}
			}
			if (wkEntry->script == NULL)
				wkEntry = NULL;
		}

		byte opcode = (byte)GetBytes(ic->code, wkEntry, ip, 0);
		if (TinselV0 && ((opcode & OPMASK) > OP_IMM))
			opcode += 3;

		debug(7, "ip=%d  Opcode %d (-> %d)", ic->ip, opcode, opcode & OPMASK);
		switch (opcode & OPMASK) {
		case OP_HALT:			// end of program

			ic->bHalt = true;
			break;

		case OP_IMM:			// loads immediate data onto stack
		case OP_STR:			// loads string handle onto stack
		case OP_FILM:			// loads film handle onto stack
		case OP_CDFILM:			// loads film handle onto stack
		case OP_FONT:			// loads font handle onto stack
		case OP_PAL:			// loads palette handle onto stack

			ic->stack[++ic->sp] = Fetch(opcode, ic->code, wkEntry, ip);
			break;

		case OP_ZERO:			// loads zero onto stack
			ic->stack[++ic->sp] = 0;
			break;

		case OP_ONE:			// loads one onto stack
			ic->stack[++ic->sp] = 1;
			break;

		case OP_MINUSONE:		// loads minus one onto stack
			ic->stack[++ic->sp] = -1;
			break;

		case OP_LOAD:			// loads local variable onto stack

			ic->stack[++ic->sp] = ic->stack[ic->bp + Fetch(opcode, ic->code, wkEntry, ip)];
			break;

		case OP_GLOAD:				// loads global variable onto stack

			tmp = Fetch(opcode, ic->code, wkEntry, ip);
			assert(0 <= tmp && tmp < numGlobals);
			ic->stack[++ic->sp] = pGlobals[tmp];
			break;

		case OP_STORE:				// pops stack and stores in local variable

			ic->stack[ic->bp + Fetch(opcode, ic->code, wkEntry, ip)] = ic->stack[ic->sp--];
			break;

		case OP_GSTORE:				// pops stack and stores in global variable

			tmp = Fetch(opcode, ic->code, wkEntry, ip);
			assert(0 <= tmp && tmp < numGlobals);
			pGlobals[tmp] = ic->stack[ic->sp--];
			break;

		case OP_CALL:				// procedure call

			tmp = Fetch(opcode, ic->code, wkEntry, ip);
			//assert(0 <= tmp && tmp < codeSize);	// TODO: Verify jumps are not out of bounds
			ic->stack[ic->sp + 1] = 0;	// static link
			ic->stack[ic->sp + 2] = ic->bp;	// dynamic link
			ic->stack[ic->sp + 3] = ip;	// return address
			ic->bp = ic->sp + 1;		// set new base pointer
			ip = tmp;	// set ip to procedure address
			break;

		case OP_LIBCALL:		// library procedure or function call

			tmp = Fetch(opcode, ic->code, wkEntry, ip);
			// NOTE: Interpret() itself is not using the coroutine facilities,
			// but still accepts a CORO_PARAM, so from the outside it looks
			// like a coroutine. In fact it may still acts as a kind of "proxy"
			// for some underlying coroutine. To enable this, we just pass on
			// 'coroParam' to CallLibraryRoutine(). If we then detect that
			// coroParam was set to a non-zero value, this means that some
			// coroutine code did run at some point, and we are now supposed
			// to sleep or die -- hence, we 'return' if coroParam != 0.
			//
			// This works because Interpret() is fully re-entrant: If we return
			// now and are later called again, then we will end up in the very
			// same spot (i.e. here).
			//
			// The reasons we do it this way, instead of turning Interpret into
			// a 'proper' coroutine are (1) we avoid implementation problems
			// (CORO_INVOKE involves adding 'case' statements, but Interpret
			// already has a huge switch/case, so that would not work out of the
			// box), (2) we incurr less overhead, (3) it's easier to debug,
			// (4) it's simply cool ;).
			tmp2 = CallLibraryRoutine(coroParam, tmp, &ic->stack[ic->sp], ic, &ic->resumeState);
			if (coroParam)
				return;
			if (!TinselV0)
				ic->sp += tmp2;
			LockCode(ic);
			if (TinselV2 && (ic->resumeState == RES_1))
				ic->resumeState = RES_NOT;
			break;

		case OP_RET:			// procedure return

			ic->sp = ic->bp - 1;		// restore stack
			ip = ic->stack[ic->sp + 3];	// return address
			ic->bp = ic->stack[ic->sp + 2];	// restore previous base pointer
			break;

		case OP_ALLOC:			// allocate storage on stack

			ic->sp += (int32)Fetch(opcode, ic->code, wkEntry, ip);
			break;

		case OP_JUMP:	// unconditional jump

			ip = Fetch(opcode, ic->code, wkEntry, ip);
			wkEntry = NULL;					// In case a jump occurs from a workaround
			break;

		case OP_JMPFALSE:	// conditional jump

			tmp = Fetch(opcode, ic->code, wkEntry, ip);
			if (ic->stack[ic->sp--] == 0) {
				// condition satisfied - do the jump
				ip = tmp;
				wkEntry = NULL;					// In case a jump occurs from a workaround
			}
			break;

		case OP_JMPTRUE:	// conditional jump

			tmp = Fetch(opcode, ic->code, wkEntry, ip);
			if (ic->stack[ic->sp--] != 0) {
				// condition satisfied - do the jump
				ip = tmp;
				wkEntry = NULL;					// In case a jump occurs from a workaround
			}
			break;

		case OP_EQUAL:			// tests top two items on stack for equality
		case OP_LESS:			// tests top two items on stack
		case OP_LEQUAL:			// tests top two items on stack
		case OP_NEQUAL:			// tests top two items on stack
		case OP_GEQUAL:			// tests top two items on stack
		case OP_GREAT:			// tests top two items on stack
		case OP_LOR:			// logical or of top two items on stack and replaces with result
		case OP_LAND:			// logical ands top two items on stack and replaces with result

			// pop one operand
			ic->sp--;
			assert(ic->sp >= 0);
			tmp = ic->stack[ic->sp];
			tmp2 = ic->stack[ic->sp + 1];

			// replace other operand with result of operation
			switch (opcode) {
			case OP_EQUAL:  tmp = (tmp == tmp2); break;
			case OP_LESS:   tmp = (tmp <  tmp2); break;
			case OP_LEQUAL: tmp = (tmp <= tmp2); break;
			case OP_NEQUAL: tmp = (tmp != tmp2); break;
			case OP_GEQUAL: tmp = (tmp >= tmp2); break;
			case OP_GREAT:  tmp = (tmp >  tmp2); break;

			case OP_LOR:    tmp = (tmp || tmp2); break;
			case OP_LAND:   tmp = (tmp && tmp2); break;
			}

			ic->stack[ic->sp] = tmp;
			break;

		case OP_PLUS:			// adds top two items on stack and replaces with result
		case OP_MINUS:			// subs top two items on stack and replaces with result
		case OP_MULT:			// multiplies top two items on stack and replaces with result
		case OP_DIV:			// divides top two items on stack and replaces with result
		case OP_MOD:			// divides top two items on stack and replaces with modulus
		case OP_AND:			// bitwise ands top two items on stack and replaces with result
		case OP_OR:				// bitwise ors top two items on stack and replaces with result
		case OP_EOR:			// bitwise exclusive ors top two items on stack and replaces with result

			// pop one operand
			ic->sp--;
			assert(ic->sp >= 0);
			tmp = ic->stack[ic->sp];
			tmp2 = ic->stack[ic->sp + 1];

			// replace other operand with result of operation
			switch (opcode) {
			case OP_PLUS:   tmp += tmp2; break;
			case OP_MINUS:  tmp -= tmp2; break;
			case OP_MULT:   tmp *= tmp2; break;
			case OP_DIV:    tmp /= tmp2; break;
			case OP_MOD:    tmp %= tmp2; break;
			case OP_AND:    tmp &= tmp2; break;
			case OP_OR:     tmp |= tmp2; break;
			case OP_EOR:    tmp ^= tmp2; break;
			}
			ic->stack[ic->sp] = tmp;
			break;

		case OP_NOT:			// logical nots top item on stack

			ic->stack[ic->sp] = !ic->stack[ic->sp];
			break;

		case OP_COMP:			// complements top item on stack
			ic->stack[ic->sp] = ~ic->stack[ic->sp];
			break;

		case OP_NEG:			// negates top item on stack
			ic->stack[ic->sp] = -ic->stack[ic->sp];
			break;

		case OP_DUP:			// duplicates top item on stack
			ic->stack[ic->sp + 1] = ic->stack[ic->sp];
			ic->sp++;
			break;

		case OP_ESCON:
			bNoPause = true;
			ic->escOn = true;
			ic->myEscape = GetEscEvents();
			break;

		case OP_ESCOFF:
			ic->escOn = false;
			ic->myEscape = 0;
			break;

		default:
			error("Interpret() - Unknown opcode");
		}

		// check for stack under-overflow
		assert(ic->sp >= 0 && ic->sp < PCODE_STACK_SIZE);
		ic->ip = ip;
		ic->fragmentPtr = wkEntry;
	} while (!ic->bHalt);

	// make sure stack is unwound
	assert(ic->sp == 0);

	FreeInterpretContextPi(ic);
}