Beispiel #1
0
// Assign the result to the appropriate _result variable
void Expression::getResult(byte operation, int32 value, byte *type) {
	if (type != 0)
		*type = operation;

	switch (operation) {
	case OP_NOT:
		if (type != 0)
			*type ^= 1;
		break;

	case OP_LOAD_IMM_INT16:
		_resultInt = value;
		break;

	case OP_LOAD_IMM_STR:
		if ((char *)decodePtr(value) != _resultStr)
			strcpy(_resultStr, (char *)decodePtr(value));
		break;

	case OP_LOAD_VAR_INT32:
	case OP_LOAD_VAR_INT32_AS_INT16:
		break;

	default:
		_resultInt = 0;
		if (type != 0)
			*type = OP_LOAD_IMM_INT16;
		break;
	}
}
Beispiel #2
0
void Expression::simpleArithmetic1(StackFrame &stackFrame) {
	switch (stackFrame.opers[-1]) {
	case OP_ADD:
		if (stackFrame.opers[-2] == OP_LOAD_IMM_STR) {
			if ((char *)decodePtr(stackFrame.values[-2]) != _resultStr) {
				strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-2]));
				stackFrame.values[-2] = encodePtr((byte *)_resultStr, kResStr);
			}
			strcat(_resultStr, (char *)decodePtr(stackFrame.values[0]));
			stackFrame.pop(2);
		}
		break;

	case OP_MUL:
		stackFrame.values[-2] *= stackFrame.values[0];
		stackFrame.pop(2);
		break;

	case OP_DIV:
		stackFrame.values[-2] /= stackFrame.values[0];
		stackFrame.pop(2);
		break;

	case OP_MOD:
		stackFrame.values[-2] %= stackFrame.values[0];
		stackFrame.pop(2);
		break;

	case OP_BITAND:
		stackFrame.values[-2] &= stackFrame.values[0];
		stackFrame.pop(2);
		break;
	}
}
Beispiel #3
0
int Expression::cmpHelper(const StackFrame &stackFrame) {
	byte type = stackFrame.opers[-3];
	int cmpTemp = 0;

	if (type == OP_LOAD_IMM_INT16) {
		cmpTemp = (int)stackFrame.values[-3] - (int)stackFrame.values[-1];
	} else if (type == OP_LOAD_IMM_STR) {
		if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) {
			strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3]));
			stackFrame.values[-3] = encodePtr((byte *)_resultStr, kResStr);
		}
		cmpTemp = strcmp(_resultStr, (char *)decodePtr(stackFrame.values[-1]));
	}

	return cmpTemp;
}
Beispiel #4
0
void Logic::formText(int32 *params) {
	// params	0 pointer to ob_graphic
	//		1 pointer to ob_speech
	//		2 pointer to ob_logic
	//		3 pointer to ob_mega
	//		4 encoded text number
	//		5 wav res id
	//		6 anim res id
	//		7 pointer to anim table
	//		8 animation mode	0 lip synced,
	//					1 just straight animation

	// There should always be a text line, as all text is derived from it.
	// If there is none, that's bad...

	if (!params[S_TEXT]) {
		warning("No text line for speech wav %d", params[S_WAV]);
		return;
	}

	ObjectSpeech obSpeech(decodePtr(params[S_OB_SPEECH]));

	// Establish the max width allowed for this text sprite.
	uint32 textWidth = obSpeech.getWidth();

	if (!textWidth)
		textWidth = 400;

	// Pull out the text line, and make the sprite and text block

	uint32 text_res = params[S_TEXT] / SIZE;
	uint32 local_text = params[S_TEXT] & 0xffff;
	byte *text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);

	// 'text + 2' to skip the first 2 bytes which form the line reference
	// number

	_speechTextBlocNo = _vm->_fontRenderer->buildNewBloc(
		text + 2, _textX, _textY,
		textWidth, obSpeech.getPen(),
		RDSPR_TRANS | RDSPR_DISPLAYALIGN,
		_vm->_speechFontId, POSITION_AT_CENTRE_OF_BASE);

	_vm->_resman->closeResource(text_res);

	// Set speech duration, in case not using a wav.
	_speechTime = strlen((char *)text) + 30;
}
Beispiel #5
0
void Logic::locateTalker(int32 *params) {
	// params:	0 pointer to ob_graphic
	//		1 pointer to ob_speech
	//		2 pointer to ob_logic
	//		3 pointer to ob_mega
	//		4 encoded text number
	//		5 wav res id
	//		6 anim res id
	//		7 pointer to anim table
	//		8 animation mode	0 lip synced,
	//					1 just straight animation

	if (!_animId) {
		// There is no animation. Assume it's voice-over text, and put
		// it at the bottom of the screen.

		_textX = 320;
		_textY = 400;
		return;
	}

	byte *file = _vm->_resman->openResource(_animId);

	// '0' means 1st frame

	CdtEntry cdt_entry;
	FrameHeader frame_head;

	cdt_entry.read(_vm->fetchCdtEntry(file, 0));
	frame_head.read(_vm->fetchFrameHeader(file, 0));

	// Note: This part of the code is quite similar to registerFrame().

	if (cdt_entry.frameType & FRAME_OFFSET) {
		// The frame has offsets, i.e. it's a scalable mega frame
		ObjectMega obMega(decodePtr(params[S_OB_MEGA]));

		uint16 scale = obMega.calcScale();

		// Calc suitable centre point above the head, based on scaled
		// height

		// just use 'feet_x' as centre
		_textX = obMega.getFeetX();

		// Add scaled y-offset to feet_y coord to get top of sprite
		_textY = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
	} else {
		// It's a non-scaling anim - calc suitable centre point above
		// the head, based on scaled width

		// x-coord + half of width
		_textX = cdt_entry.x + frame_head.width / 2;
		_textY = cdt_entry.y;
	}

	_vm->_resman->closeResource(_animId);

	// Leave space above their head
	_textY -= GAP_ABOVE_HEAD;

	// Adjust the text coords for RDSPR_DISPLAYALIGN

	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();

	_textX -= screenInfo->scroll_offset_x;
	_textY -= screenInfo->scroll_offset_y;
}
Beispiel #6
0
// Complex arithmetics with brackets
bool Expression::complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart) {
	switch (stackFrame.opers[-2]) {
	case OP_ADD:
		if (stack.opers[brackStart] == OP_LOAD_IMM_INT16) {
			stack.values[brackStart] += stackFrame.values[-1];
		} else if (stack.opers[brackStart] == OP_LOAD_IMM_STR) {
			if ((char *)decodePtr(stack.values[brackStart]) != _resultStr) {
				strcpy(_resultStr, (char *)decodePtr(stack.values[brackStart]));
				stack.values[brackStart] =
					encodePtr((byte *)_resultStr, kResStr);
			}
			strcat(_resultStr, (char *)decodePtr(stackFrame.values[-1]));
		}
		stackFrame.pop(2);
		break;

	case OP_SUB:
		stack.values[brackStart] -= stackFrame.values[-1];
		stackFrame.pop(2);
		break;

	case OP_BITOR:
		stack.values[brackStart] |= stackFrame.values[-1];
		stackFrame.pop(2);
		break;

	case OP_MUL:
		stackFrame.values[-3] *= stackFrame.values[-1];
		stackFrame.pop(2);
		break;

	case OP_DIV:
		stackFrame.values[-3] /= stackFrame.values[-1];
		stackFrame.pop(2);
		break;

	case OP_MOD:
		stackFrame.values[-3] %= stackFrame.values[-1];
		stackFrame.pop(2);
		break;

	case OP_BITAND:
		stackFrame.values[-3] &= stackFrame.values[-1];
		stackFrame.pop(2);
		break;

	case OP_OR:
		// (x OR false) == x
		// (x OR true) == true
		if (stackFrame.opers[-3] == GOB_FALSE)
			stackFrame.opers[-3] = stackFrame.opers[-1];
		stackFrame.pop(2);
		break;

	case OP_AND:
		// (x AND false) == false
		// (x AND true) == x
		if (stackFrame.opers[-3] == GOB_TRUE)
			stackFrame.opers[-3] = stackFrame.opers[-1];
		stackFrame.pop(2);
		break;

	case OP_LESS:
		stackFrame.opers[-3] = (cmpHelper(stackFrame) < 0) ? GOB_TRUE : GOB_FALSE;
		stackFrame.pop(2);
		break;

	case OP_LEQ:
		stackFrame.opers[-3] = (cmpHelper(stackFrame) <= 0) ? GOB_TRUE : GOB_FALSE;
		stackFrame.pop(2);
		break;

	case OP_GREATER:
		stackFrame.opers[-3] = (cmpHelper(stackFrame) > 0) ? GOB_TRUE : GOB_FALSE;
		stackFrame.pop(2);
		break;

	case OP_GEQ:
		stackFrame.opers[-3] = (cmpHelper(stackFrame) >= 0) ? GOB_TRUE : GOB_FALSE;
		stackFrame.pop(2);
		break;

	case OP_EQ:
		stackFrame.opers[-3] = (cmpHelper(stackFrame) == 0) ? GOB_TRUE : GOB_FALSE;
		stackFrame.pop(2);
		break;

	case OP_NEQ:
		stackFrame.opers[-3] = (cmpHelper(stackFrame) != 0) ? GOB_TRUE : GOB_FALSE;
		stackFrame.pop(2);
		break;

	default:
		return true;
	}

	return false;
}
Beispiel #7
0
int16 Expression::parseExpr(byte stopToken, byte *type) {
	Stack stack;
	StackFrame stackFrame(stack);
	byte operation;
	int16 brackStart;
	uint32 varBase;

	while (true) {
		getVarBase(varBase);

		stackFrame.push();

		operation = _vm->_game->_script->readByte();
		if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) {

			loadValue(operation, varBase, stackFrame);

			if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) {
				stackFrame.pop();

				if (*stackFrame.opers == OP_NEG) {
					*stackFrame.opers = OP_LOAD_IMM_INT16;
					stackFrame.values[0] = -stackFrame.values[1];
				} else
					*stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE;
			}

			if (stackFrame.pos <= 0)
				continue;

			simpleArithmetic1(stackFrame);

			continue;
		} // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC)

		if ((operation == stopToken) || (operation == OP_OR) ||
				(operation == OP_AND) || (operation == OP_END_EXPR)) {
			while (stackFrame.pos >= 2) {
				if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) &&
						((operation == OP_END_EXPR) || (operation == stopToken))) {
					stackFrame.opers[-2] = stackFrame.opers[-1];
					if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR))
						stackFrame.values[-2] = stackFrame.values[-1];

					stackFrame.pop();

					simpleArithmetic2(stackFrame);

					if (operation != stopToken)
						break;
				}	// if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...)

				for (brackStart = (stackFrame.pos - 2); (brackStart > 0) &&
				    (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR);
						brackStart--)
					;

				if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR))
					brackStart++;

				if (complexArithmetic(stack, stackFrame, brackStart))
					break;

			}	// while (stackFrame.pos >= 2)

			if ((operation == OP_OR) || (operation == OP_AND)) {
				if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) {
					if (stackFrame.values[-1] != 0)
						stackFrame.opers[-1] = GOB_TRUE;
					else
						stackFrame.opers[-1] = GOB_FALSE;
				}

				if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) ||
				    ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) {
					if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) {
						skipExpr(OP_END_EXPR);
						stackFrame.opers[-2] = stackFrame.opers[-1];
						stackFrame.pop(2);
					} else {
						skipExpr(stopToken);
					}
					operation = _vm->_game->_script->peekByte(-1);
					if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) {
						if (stackFrame.opers[0] == GOB_FALSE)
							stackFrame.opers[-1] = GOB_TRUE;
						else
							stackFrame.opers[-1] = GOB_FALSE;

						stackFrame.pop();
					}
				} else
					stackFrame.opers[0] = operation;
			} else
				stackFrame.pop();

			if (operation != stopToken)
				continue;

			getResult(stack.opers[0], stack.values[0], type);

			return 0;
		}		// (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR)

		if ((operation < OP_NEG) || (operation > OP_NOT)) {
			if ((operation < OP_LESS) || (operation > OP_NEQ))
				continue;

			if (stackFrame.pos > 2) {
				if (stackFrame.opers[-2] == OP_ADD) {
					if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) {
						stackFrame.values[-3] += stackFrame.values[-1];
					} else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) {
						if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) {
							strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3]));
							stackFrame.values[-3] = encodePtr((byte *)_resultStr, kResStr);
						}
						strcat(_resultStr, (char *)decodePtr(stackFrame.values[-1]));
					}
					stackFrame.pop(2);

				} else if (stackFrame.opers[-2] == OP_SUB) {
					stackFrame.values[-3] -= stackFrame.values[-1];
					stackFrame.pop(2);
				} else if (stackFrame.opers[-2] == OP_BITOR) {
					stackFrame.values[-3] |= stackFrame.values[-1];
					stackFrame.pop(2);
				}
			}
		}
		*stackFrame.opers = operation;
	}
}