Esempio n. 1
0
void Mechanical::o_snakeBoxTrigger(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	debugC(kDebugScript, "Opcode %d: Trigger Playing Of Snake Movie", op);

	// Used on Mechanical Card 6043 (Weapons Rack with Snake Box)
	_snakeBox->playMovie();
}
Esempio n. 2
0
/**
 * Main interface point for specifying player atcions
 */
void PlayerEvent(PLR_EVENT pEvent, const Common::Point &coOrds) {
	// Logging of player actions
	const char *actionList[] = {
		"PLR_PROV_WALKTO", "PLR_WALKTO", "PLR_LOOK", "PLR_ACTION", "PLR_ESCAPE",
		"PLR_MENU", "PLR_QUIT", "PLR_PGUP", "PLR_PGDN", "PLR_HOME", "PLR_END",
		"PLR_DRAG1_START", "PLR_DRAG1_END", "PLR_DRAG2_START", "PLR_DRAG2_END",
		"PLR_JUMP", "PLR_NOEVENT", "PLR_SAVE", "PLR_LOAD", "PLR_WHEEL_UP",
		"PLR_WHEEL_DOWN"};
	debugC(DEBUG_BASIC, kTinselDebugActions, "%s - (%d,%d)",
		actionList[pEvent], coOrds.x, coOrds.y);
	static uint32 lastRealAction = 0;	// FIXME: Avoid non-const global vars

	// This stuff to allow F1 key during startup.
	if (g_bEnableMenu && pEvent == PLR_MENU)
		Control(CONTROL_ON);
	else
		IncUserEvents();

	if (pEvent == PLR_ESCAPE) {
		++g_escEvents;
		++g_leftEvents;		// Yes, I do mean this
	} else if ((pEvent == PLR_PROV_WALKTO)
			|| (pEvent == PLR_WALKTO)
			|| (pEvent == PLR_LOOK)
			|| (pEvent == PLR_ACTION)) {
		++g_leftEvents;
	}

	// Only allow events if player control is on
	if (!ControlIsOn() && (pEvent != PLR_DRAG1_END))
		return;

	if (TinselV2 && InventoryActive()) {
		int x, y;
		PlayfieldGetPos(FIELD_WORLD, &x, &y);
		EventToInventory(pEvent, Common::Point(coOrds.x - x, coOrds.y - y));
		return;
	}

	switch (pEvent) {
	case PLR_QUIT:
		OpenMenu(QUIT_MENU);
		break;

	case PLR_MENU:
		OpenMenu(MAIN_MENU);
		break;

	case PLR_JUMP:
		OpenMenu(HOPPER_MENU1);
		break;

	case PLR_SAVE:
		OpenMenu(SAVE_MENU);
		break;

	case PLR_LOAD:
		OpenMenu(LOAD_MENU);
		break;

	case PLR_PROV_WALKTO:		// Provisional WALKTO !
		ProcessUserEvent(PROV_WALKTO, coOrds);
		break;

	case PLR_WALKTO:
		REAL_ACTION_CHECK;

		if (TinselV2 || !InventoryActive())
			ProcessUserEvent(WALKTO, coOrds, PLR_SLEFT);
		else
			EventToInventory(PLR_SLEFT, coOrds);
		break;

	case PLR_ACTION:
		REAL_ACTION_CHECK;

		if (TinselV2 || !InventoryActive())
			ProcessUserEvent(ACTION, coOrds, PLR_DLEFT);
		else
			EventToInventory(PLR_DLEFT, coOrds);
		break;

	case PLR_LOOK:
		REAL_ACTION_CHECK;

		if (TinselV2 || !InventoryActive())
			ProcessUserEvent(LOOK, coOrds, PLR_SRIGHT);
		else
			EventToInventory(PLR_SRIGHT, coOrds);
		break;

	default:
		if (InventoryActive())
			EventToInventory(pEvent, coOrds);
		break;
	}
}
Esempio n. 3
0
void Inter_v6::o6_playVmdOrMusic() {
	char fileName[128];
	int16 x, y;
	int16 startFrame;
	int16 lastFrame;
	int16 breakKey;
	int16 flags;
	int16 palStart;
	int16 palEnd;
	uint16 palCmd;
	bool close;

	_vm->_game->_script->evalExpr(0);
	strncpy0(fileName, _vm->_game->_script->getResultStr(), 127);

	x = _vm->_game->_script->readValExpr();
	y = _vm->_game->_script->readValExpr();
	startFrame = _vm->_game->_script->readValExpr();
	lastFrame = _vm->_game->_script->readValExpr();
	breakKey = _vm->_game->_script->readValExpr();
	flags = _vm->_game->_script->readValExpr();
	palStart = _vm->_game->_script->readValExpr();
	palEnd = _vm->_game->_script->readValExpr();
	palCmd = 1 << (flags & 0x3F);

	debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
			"paletteCmd %d (%d - %d), flags %X", fileName, x, y, startFrame, lastFrame,
			palCmd, palStart, palEnd, flags);

	close = false;
	if (lastFrame == -1) {
		close = true;
	} else if (lastFrame == -5) {
		_vm->_sound->bgStop();
		return;
	} else if (lastFrame == -9) {
		if (!strchr(fileName, '.'))
			strcat(fileName, ".WA8");

		probe16bitMusic(fileName);

		_vm->_sound->bgStop();
		_vm->_sound->bgPlay(fileName, SOUND_WAV);
		return;
	} else if (lastFrame == -10) {
		_vm->_vidPlayer->primaryClose();
		warning("Urban Stub: Video/Music command -10 (close video?)");
		return;
	} else if (lastFrame < 0) {
		warning("Unknown Video/Music command: %d, %s", lastFrame, fileName);
		return;
	}

	if (startFrame == -2) {
		startFrame = 0;
		lastFrame = -1;
		close = false;
	}

	if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) {
		WRITE_VAR(11, (uint32) -1);
		return;
	}

	if (startFrame >= 0)
		_vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey,
				palCmd, palStart, palEnd, 0, -1, false, -1, true);

	if (close)
		_vm->_vidPlayer->primaryClose();
}
Esempio n. 4
0
/**
 * Add up all the object values and all the bonus points
 */
void HugoEngine::calcMaxScore() {
	debugC(1, kDebugEngine, "calcMaxScore");

	_maxscore = _object->calcMaxScore() + _scheduler->calcMaxPoints();
}
Esempio n. 5
0
/**
 * Update all object positions.  Process object 'local' events
 * including boundary events and collisions
 */
void ObjectHandler_v3d::moveObjects() {
	debugC(4, kDebugObject, "moveObjects");

	// Added to DOS version in order to handle mouse properly
	// Do special route processing
	_vm->_route->processRoute();

	// Perform any adjustments to velocity based on special path types
	// and store all (visible) object baselines into the boundary file.
	// Don't store foreground or background objects
	for (int i = 0; i < _numObj; i++) {
		object_t *obj = &_objects[i];               // Get pointer to object
		seq_t *currImage = obj->currImagePtr;       // Get ptr to current image
		if (obj->screenIndex == *_vm->_screen_p) {
			switch (obj->pathType) {
			case kPathChase:
			case kPathChase2: {
				int8 radius = obj->radius;          // Default to object's radius
				if (radius < 0)                     // If radius infinity, use closer value
					radius = kStepDx;

				// Allowable motion wrt boundary
				int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - currImage->x1;
				int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - currImage->y2 - 1;
				if (abs(dx) <= radius)
					obj->vx = 0;
				else
					obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath);
				if (abs(dy) <= radius)
					obj->vy = 0;
				else
					obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath);

				// Set first image in sequence (if multi-seq object)
				switch (obj->seqNumb) {
				case 4:
					if (!obj->vx) {                 // Got 4 directions
						if (obj->vx != obj->oldvx) { // vx just stopped
							if (dy >= 0)
								obj->currImagePtr = obj->seqList[DOWN].seqPtr;
							else
								obj->currImagePtr = obj->seqList[_UP].seqPtr;
						}
					} else if (obj->vx != obj->oldvx) {
						if (dx > 0)
							obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
						else
							obj->currImagePtr = obj->seqList[LEFT].seqPtr;
					}
					break;
				case 3:
				case 2:
					if (obj->vx != obj->oldvx) {    // vx just stopped
						if (dx > 0)                 // Left & right only
							obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
						else
							obj->currImagePtr = obj->seqList[LEFT].seqPtr;
					}
					break;
				}

				if (obj->vx || obj->vy) {
					obj->cycling = kCycleForward;
				} else {
					obj->cycling = kCycleNotCycling;
					boundaryCollision(obj);         // Must have got hero!
				}
				obj->oldvx = obj->vx;
				obj->oldvy = obj->vy;
				currImage = obj->currImagePtr;      // Get (new) ptr to current image
				break;
				}
			case kPathWander2:
			case kPathWander:
				if (!_vm->_rnd->getRandomNumber(3 * _vm->_normalTPS)) {       // Kick on random interval
					obj->vx = _vm->_rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath;
					obj->vy = _vm->_rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath;

					// Set first image in sequence (if multi-seq object)
					if (obj->seqNumb > 1) {
						if (!obj->vx && (obj->seqNumb >= 4)) {
							if (obj->vx != obj->oldvx) { // vx just stopped
								if (obj->vy > 0)
									obj->currImagePtr = obj->seqList[DOWN].seqPtr;
								else
									obj->currImagePtr = obj->seqList[_UP].seqPtr;
							}
						} else if (obj->vx != obj->oldvx) {
							if (obj->vx > 0)
								obj->currImagePtr = obj->seqList[RIGHT].seqPtr;
							else
								obj->currImagePtr = obj->seqList[LEFT].seqPtr;
						}
					}
					obj->oldvx = obj->vx;
					obj->oldvy = obj->vy;
					currImage = obj->currImagePtr;  // Get (new) ptr to current image
				}
				if (obj->vx || obj->vy)
					obj->cycling = kCycleForward;

				break;
			default:
				; // Really, nothing
			}
			// Store boundaries
			if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
				storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2);
		}
	}

	// Move objects, allowing for boundaries
	for (int i = 0; i < _numObj; i++) {
		object_t *obj = &_objects[i];                         // Get pointer to object
		if ((obj->screenIndex == *_vm->_screen_p) && (obj->vx || obj->vy)) {
			// Only process if it's moving

			// Do object movement.  Delta_x,y return allowed movement in x,y
			// to move as close to a boundary as possible without crossing it.
			seq_t *currImage = obj->currImagePtr;   // Get ptr to current image
			// object coordinates
			int x1 = obj->x + currImage->x1;        // Left edge of object
			int x2 = obj->x + currImage->x2;        // Right edge
			int y1 = obj->y + currImage->y1;        // Top edge
			int y2 = obj->y + currImage->y2;        // Bottom edge

			if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
				clearBoundary(x1, x2, y2);          // Clear our own boundary

			// Allowable motion wrt boundary
			int dx = deltaX(x1, x2, obj->vx, y2);
			if (dx != obj->vx) {
				// An object boundary collision!
				boundaryCollision(obj);
				obj->vx = 0;
			}

			int dy = deltaY(x1, x2, obj->vy, y2);
			if (dy != obj->vy) {
				// An object boundary collision!
				boundaryCollision(obj);
				obj->vy = 0;
			}

			if ((obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
				storeBoundary(x1, x2, y2);          // Re-store our own boundary

			obj->x += dx;                           // Update object position
			obj->y += dy;

			// Don't let object go outside screen
			if (x1 < kEdge)
				obj->x = kEdge2;
			if (x2 > (kXPix - kEdge))
				obj->x = kXPix - kEdge2 - (x2 - x1);
			if (y1 < kEdge)
				obj->y = kEdge2;
			if (y2 > (kYPix - kEdge))
				obj->y = kYPix - kEdge2 - (y2 - y1);

			if ((obj->vx == 0) && (obj->vy == 0) && (obj->pathType != kPathWander2) && (obj->pathType != kPathChase2))
				obj->cycling = kCycleNotCycling;
		}
	}

	// Clear all object baselines from the boundary file.
	for (int i = 0; i < _numObj; i++) {
		object_t *obj = &_objects[i];               // Get pointer to object
		seq_t *currImage = obj->currImagePtr;       // Get ptr to current image
		if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > kCycleAlmostInvisible) && (obj->priority == kPriorityFloating))
			clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2);
	}

	// If maze mode is enabled, do special maze processing
	if (_vm->_maze.enabledFl) {
		seq_t *currImage = _vm->_hero->currImagePtr;// Get ptr to current image
		// hero coordinates
		int x1 = _vm->_hero->x + currImage->x1;     // Left edge of object
		int x2 = _vm->_hero->x + currImage->x2;     // Right edge
		int y1 = _vm->_hero->y + currImage->y1;     // Top edge
		int y2 = _vm->_hero->y + currImage->y2;     // Bottom edge

		_vm->_scheduler->processMaze(x1, x2, y1, y2);
	}
}
Esempio n. 6
0
void Inter_v7::o7_playVmdOrMusic() {
	Common::String file = _vm->_game->_script->evalString();

	VideoPlayer::Properties props;

	props.x          = _vm->_game->_script->readValExpr();
	props.y          = _vm->_game->_script->readValExpr();
	props.startFrame = _vm->_game->_script->readValExpr();
	props.lastFrame  = _vm->_game->_script->readValExpr();
	props.breakKey   = _vm->_game->_script->readValExpr();
	props.flags      = _vm->_game->_script->readValExpr();
	props.palStart   = _vm->_game->_script->readValExpr();
	props.palEnd     = _vm->_game->_script->readValExpr();
	props.palCmd     = 1 << (props.flags & 0x3F);
	props.forceSeek  = true;

	debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
			"paletteCmd %d (%d - %d), flags %X", file.c_str(),
			props.x, props.y, props.startFrame, props.lastFrame,
			props.palCmd, props.palStart, props.palEnd, props.flags);

	if (file == "RIEN") {
		_vm->_vidPlayer->closeAll();
		return;
	}

	bool close = false;
	if (props.lastFrame == -1) {
		close = true;
	} else if (props.lastFrame == -3) {

		if (file.empty()) {
			_vm->_vidPlayer->closeVideo(_vm->_mult->_objects[props.startFrame].videoSlot - 1);
			_vm->_mult->_objects[props.startFrame].videoSlot = 0;
			return;
		}

		props.flags  = VideoPlayer::kFlagOtherSurface;
		props.sprite = -1;

		_vm->_mult->_objects[props.startFrame].pAnimData->animation = -props.startFrame - 1;

		if (_vm->_mult->_objects[props.startFrame].videoSlot > 0)
			_vm->_vidPlayer->closeVideo(_vm->_mult->_objects[props.startFrame].videoSlot - 1);

		uint32 x = props.x;
		uint32 y = props.y;

		int slot = _vm->_vidPlayer->openVideo(false, file, props);

		_vm->_mult->_objects[props.startFrame].videoSlot = slot + 1;

		if (x == 0xFFFFFFFF) {
			*_vm->_mult->_objects[props.startFrame].pPosX = _vm->_vidPlayer->getDefaultX(slot);
			*_vm->_mult->_objects[props.startFrame].pPosY = _vm->_vidPlayer->getDefaultY(slot);
		} else {
			*_vm->_mult->_objects[props.startFrame].pPosX = x;
			*_vm->_mult->_objects[props.startFrame].pPosY = y;
		}

		return;
	} else if (props.lastFrame == -4) {
		warning("Woodruff Stub: Video/Music command -4: Play background video %s", file.c_str());
		return;
	} else if (props.lastFrame == -5) {
//		warning("Urban/Playtoons Stub: Stop without delay");
		_vm->_sound->bgStop();
		return;
	} else if (props.lastFrame == -6) {
//		warning("Urban/Playtoons Stub: Video/Music command -6 (cache video)");
		return;
	} else if (props.lastFrame == -7) {
//		warning("Urban/Playtoons Stub: Video/Music command -6 (flush cache)");
		return;
	} else if ((props.lastFrame == -8) || (props.lastFrame == -9)) {
		if (!file.contains('.'))
			file += ".WA8";

		probe16bitMusic(file);

		if (props.lastFrame == -9)
			debugC(0, kDebugVideo, "Urban/Playtoons Stub: Delayed music stop?");

		_vm->_sound->bgStop();
		_vm->_sound->bgPlay(file.c_str(), SOUND_WAV);
		return;
	} else if (props.lastFrame <= -10) {
		_vm->_vidPlayer->closeVideo();

		if (!(props.flags & VideoPlayer::kFlagNoVideo))
			props.loop = true;

	} else if (props.lastFrame < 0) {
		warning("Urban/Playtoons Stub: Unknown Video/Music command: %d, %s", props.lastFrame, file.c_str());
		return;
	}

	if (props.startFrame == -2) {
		props.startFrame = 0;
		props.lastFrame  = -1;
		props.noBlock    = true;
	}

	_vm->_vidPlayer->evaluateFlags(props);

	bool primary = true;
	if (props.noBlock && (props.flags & VideoPlayer::kFlagNoVideo))
		primary = false;

	int slot = 0;
	if (!file.empty() && ((slot = _vm->_vidPlayer->openVideo(primary, file, props)) < 0)) {
		WRITE_VAR(11, (uint32) -1);
		return;
	}

	if (props.hasSound)
		_vm->_vidPlayer->closeLiveSound();

	if (props.startFrame >= 0)
		_vm->_vidPlayer->play(slot, props);

	if (close && !props.noBlock) {
		if (!props.canceled)
			_vm->_vidPlayer->waitSoundEnd(slot);
		_vm->_vidPlayer->closeVideo(slot);
	}

}
Esempio n. 7
0
void Inter_v6::o6_playVmdOrMusic() {
	Common::String file = _vm->_game->_script->evalString();

	VideoPlayer::Properties props;

	props.x          = _vm->_game->_script->readValExpr();
	props.y          = _vm->_game->_script->readValExpr();
	props.startFrame = _vm->_game->_script->readValExpr();
	props.lastFrame  = _vm->_game->_script->readValExpr();
	props.breakKey   = _vm->_game->_script->readValExpr();
	props.flags      = _vm->_game->_script->readValExpr();
	props.palStart   = _vm->_game->_script->readValExpr();
	props.palEnd     = _vm->_game->_script->readValExpr();
	props.palCmd     = 1 << (props.flags & 0x3F);
	props.forceSeek  = true;

	debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
			"paletteCmd %d (%d - %d), flags %X", file.c_str(),
			props.x, props.y, props.startFrame, props.lastFrame,
			props.palCmd, props.palStart, props.palEnd, props.flags);

	// WORKAROUND: When taking the music sheet from Dr. Dramish's car,
	//             the video that lets the sheet vanish is missing. We'll
	//             play the one where the sheet is already gone instead.
	if (_vm->isCurrentTot("avt005.tot") && file.equalsIgnoreCase("MXRAMPART"))
		file = "PLCOFDR2";

	if (file == "RIEN") {
		_vm->_vidPlayer->closeAll();
		return;
	}

	bool close = false;
	if (props.lastFrame == -1) {
		close = true;
	} else if (props.lastFrame == -5) {
//		warning("Urban/Playtoons Stub: Stop without delay");
		_vm->_sound->bgStop();
		return;
	} else if (props.lastFrame == -6) {
//		warning("Urban/Playtoons Stub: Video/Music command -6 (cache video)");
		return;
	} else if (props.lastFrame == -7) {
//		warning("Urban/Playtoons Stub: Video/Music command -6 (flush cache)");
		return;
	} else if ((props.lastFrame == -8) || (props.lastFrame == -9)) {
		if (!file.contains('.'))
			file += ".WA8";

		probe16bitMusic(file);

		if (props.lastFrame == -9)
			debugC(0, kDebugVideo, "Urban/Playtoons Stub: Delayed music stop?");

		_vm->_sound->bgStop();
		_vm->_sound->bgPlay(file.c_str(), SOUND_WAV);
		return;
	} else if (props.lastFrame <= -10) {
		_vm->_vidPlayer->closeVideo();

		if (!(props.flags & VideoPlayer::kFlagNoVideo))
			props.loop = true;

	} else if (props.lastFrame < 0) {
		warning("Urban/Playtoons Stub: Unknown Video/Music command: %d, %s", props.lastFrame, file.c_str());
		return;
	}

	if (props.startFrame == -2) {
		props.startFrame = 0;
		props.lastFrame  = -1;
		props.noBlock    = true;
	}

	_vm->_vidPlayer->evaluateFlags(props);

	bool primary = true;
	if (props.noBlock && (props.flags & VideoPlayer::kFlagNoVideo))
		primary = false;

	int slot = 0;
	if (!file.empty() && ((slot = _vm->_vidPlayer->openVideo(primary, file, props)) < 0)) {
		WRITE_VAR(11, (uint32) -1);
		return;
	}

	if (props.hasSound)
		_vm->_vidPlayer->closeLiveSound();

	if (props.startFrame >= 0)
		_vm->_vidPlayer->play(slot, props);

	if (close && !props.noBlock) {
		if (!props.canceled)
			_vm->_vidPlayer->waitSoundEnd(slot);
		_vm->_vidPlayer->closeVideo(slot);
	}

}
Esempio n. 8
0
bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) {
	assert(seqData);

	static const SeqEntry floppySeqProcs[] = {
		// 0x00
		SEQOP(3, s1_wsaOpen),
		SEQOP(2, s1_wsaClose),
		SEQOP(6, s1_wsaPlayFrame),
		SEQOP(2, s1_wsaPlayNextFrame),
		// 0x04
		SEQOP(2, s1_wsaPlayPrevFrame),
		SEQOP(5, s1_drawShape),
		SEQOP(3, s1_waitTicks),
		SEQOP(3, s1_copyWaitTicks),
		// 0x08
		SEQOP(1, s1_shuffleScreen),
		SEQOP(1, s1_copyView),
		SEQOP(2, s1_loopInit),
		SEQOP(4, s1_loopInc),
		// 0x0C
		SEQOP(2, s1_loadPalette),
		SEQOP(2, s1_loadBitmap),
		SEQOP(1, s1_fadeToBlack),
		SEQOP(2, s1_printText),
		// 0x10
		SEQOP(6, s1_printTalkText),
		SEQOP(1, s1_restoreTalkText),
		SEQOP(1, s1_clearCurrentScreen),
		SEQOP(1, s1_break),
		// 0x14
		SEQOP(1, s1_fadeFromBlack),
		SEQOP(3, s1_copyRegion),
		SEQOP(2, s1_copyRegionSpecial),
		SEQOP(9, s1_fillRect),
		// 0x18
		SEQOP(2, s1_playEffect),
		SEQOP(2, s1_playTrack),
		SEQOP(1, s1_allocTempBuffer),
		SEQOP(1, s1_textDisplayEnable),
		// 0x1C
		SEQOP(1, s1_textDisplayDisable),
		SEQOP(1, s1_endOfScript)
	};

	static const SeqEntry cdromSeqProcs[] = {
		// 0x00
		SEQOP(3, s1_wsaOpen),
		SEQOP(2, s1_wsaClose),
		SEQOP(6, s1_wsaPlayFrame),
		SEQOP(2, s1_wsaPlayNextFrame),
		// 0x04
		SEQOP(2, s1_wsaPlayPrevFrame),
		SEQOP(5, s1_drawShape),
		SEQOP(3, s1_waitTicks),
		SEQOP(3, s1_waitTicks),
		// 0x08
		SEQOP(3, s1_copyWaitTicks),
		SEQOP(1, s1_shuffleScreen),
		SEQOP(1, s1_copyView),
		SEQOP(2, s1_loopInit),
		// 0x0C
		SEQOP(4, s1_loopInc),
		SEQOP(4, s1_loopInc),
		SEQOP(2, s1_skip),
		SEQOP(2, s1_loadPalette),
		// 0x10
		SEQOP(2, s1_loadBitmap),
		SEQOP(1, s1_fadeToBlack),
		SEQOP(2, s1_printText),
		SEQOP(6, s1_printTalkText),
		// 0x14
		SEQOP(1, s1_restoreTalkText),
		SEQOP(1, s1_clearCurrentScreen),
		SEQOP(1, s1_break),
		SEQOP(1, s1_fadeFromBlack),
		// 0x18
		SEQOP(3, s1_copyRegion),
		SEQOP(2, s1_copyRegionSpecial),
		SEQOP(9, s1_fillRect),
		SEQOP(2, s1_playEffect),
		// 0x1C
		SEQOP(2, s1_playTrack),
		SEQOP(1, s1_allocTempBuffer),
		SEQOP(1, s1_textDisplayEnable),
		SEQOP(1, s1_textDisplayDisable),
		// 0x20
		SEQOP(1, s1_endOfScript),
		SEQOP(1, s1_loadIntroVRM),
		SEQOP(2, s1_playVocFile),
		SEQOP(1, s1_miscUnk3),
		// 0x24
		SEQOP(2, s1_prefetchVocFile)
	};

	const SeqEntry *commands;
	int numCommands;

	if (_vm->gameFlags().isTalkie) {
		commands = cdromSeqProcs;
		numCommands = ARRAYSIZE(cdromSeqProcs);
	} else {
		commands = floppySeqProcs;
		numCommands = ARRAYSIZE(floppySeqProcs);
	}

	bool seqSkippedFlag = false;

	_seqData = seqData;

	_seqDisplayedTextTimer = 0xFFFFFFFF;
	_seqDisplayTextFlag = false;
	_seqDisplayedTextX = 0;
	_seqDisplayedText = 0;
	_seqDisplayedChar = 0;
	_seqTalkTextRestored = false;
	_seqTalkTextPrinted = false;

	_seqQuitFlag = false;
	_seqWsaCurDecodePage = 0;

	for (int i = 0; i < 20; ++i) {
		_seqLoopTable[i].ptr = 0;
		_seqLoopTable[i].count = 0xFFFF;
	}

	memset(_seqMovies, 0, sizeof(_seqMovies));

	_screen->_curPage = 0;
	while (!_seqQuitFlag && !_vm->shouldQuit()) {
		if (skipSeq && _vm->seq_skipSequence()) {
			while (1) {
				uint8 code = *_seqData;
				if (commands[code].proc == &SeqPlayer::s1_endOfScript || commands[code].proc == &SeqPlayer::s1_break)
					break;

				_seqData += commands[code].len;
			}
			skipSeq = false;
			seqSkippedFlag = true;
		}
		// used in Kallak writing intro
		if (_seqDisplayTextFlag && _seqDisplayedTextTimer != 0xFFFFFFFF && _vm->textEnabled()) {
			if (_seqDisplayedTextTimer < _system->getMillis()) {
				char charStr[3];
				charStr[0] = _vm->seqTextsTable()[_seqDisplayedText][_seqDisplayedChar];
				charStr[1] = charStr[2] = '\0';
				if (_vm->gameFlags().lang == Common::JA_JPN)
					charStr[1] = _vm->seqTextsTable()[_seqDisplayedText][++_seqDisplayedChar];
				_screen->printText(charStr, _seqDisplayedTextX, 180, 0xF, 0xC);
				_seqDisplayedTextX += _screen->getCharWidth((uint8)charStr[0]);
				++_seqDisplayedChar;

				if (_vm->seqTextsTable()[_seqDisplayedText][_seqDisplayedChar] == '\0')
					_seqDisplayedTextTimer = 0xFFFFFFFF;
				else
					_seqDisplayedTextTimer = _system->getMillis() + 1000 / ((_vm->gameFlags().lang == Common::FR_FRA) ? 120 : 60);
			}
		}

		uint8 seqCode = *_seqData++;
		if (seqCode < numCommands) {
			SeqProc currentProc = commands[seqCode].proc;
			debugC(5, kDebugLevelSequence, "0x%.4X seqCode = %d (%s)", (uint16)(_seqData - 1 - seqData), seqCode, commands[seqCode].desc);
			(this->*currentProc)();
		} else {
			error("Invalid sequence opcode %d called from 0x%.04X", seqCode, (uint16)(_seqData - 1 - seqData));
		}

		_screen->updateScreen();
	}
	delete[] _specialBuffer;
	_specialBuffer = 0;

	for (uint i = 0; i < ARRAYSIZE(_seqMovies); ++i) {
		delete _seqMovies[i].movie;
		_seqMovies[i].movie = 0;
	}
	return seqSkippedFlag;
}
Esempio n. 9
0
bool VDXPlayer::playFrameInternal() {
	byte currRes = 0x80;
	Common::ReadStream *vdxData = 0;
	while (currRes == 0x80) {
		currRes = _file->readByte();

		// Skip unknown data: 1 byte, ref Edward
		byte tmp = _file->readByte();

		uint32 compSize = _file->readUint32LE();
		uint8 lengthmask = _file->readByte();
		uint8 lengthbits = _file->readByte();

		if (_file->eos())
			break;

		debugC(5, kDebugVideo | kDebugUnknown, "Groovie::VDX: Edward = 0x%04X", tmp);

		// Read the chunk data and decompress if needed
		if (compSize)
			vdxData = _file->readStream(compSize);

		if (lengthmask && lengthbits) {
			Common::ReadStream *decompData = new LzssReadStream(vdxData, lengthmask, lengthbits);
			delete vdxData;
			vdxData = decompData;
		}

		// Use the current chunk
		switch (currRes) {
			case 0x00:
				debugC(6, kDebugVideo, "Groovie::VDX: Replay frame");
				break;
			case 0x20:
				debugC(5, kDebugVideo, "Groovie::VDX: Still frame");
				getStill(vdxData);
				break;
			case 0x25:
				debugC(5, kDebugVideo, "Groovie::VDX: Animation frame");
				getDelta(vdxData);
				break;
			case 0x80:
				debugC(5, kDebugVideo, "Groovie::VDX: Sound resource");
				chunkSound(vdxData);
				break;
			default:
				error("Groovie::VDX: Invalid resource type: %d", currRes);
		}
		delete vdxData;
		vdxData = 0;
	}

	// Wait until the current frame can be shown

	if (!DebugMan.isDebugChannelEnabled(kDebugFast)) {
		waitFrame();
	}
	// TODO: Move it to a better place
	// Update the screen
	if (currRes == 0x25) {
		//if (_flagSeven) {
			//_vm->_graphicsMan->mergeFgAndBg();
		//}
		_vm->_graphicsMan->updateScreen(_bg);
	}

	// Report the end of the video if we reached the end of the file or if we
	// just wanted to play one frame.
	if (_file->eos() || _flagFirstFrame) {
		_origX = _origY = 0;
		return 1;
	} else {
		return 0;
	}
}
Esempio n. 10
0
void Mechanical::o_throne_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	// Used on Card 6238 (Sirrus' Throne) and Card 6027 (Achenar's Throne)
	debugC(kDebugScript, "Opcode %d: Brother throne init", op);

	_invokingResource->setEnabled(getVar(var));
}
Esempio n. 11
0
void Mechanical::o_snakeBox_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	debugC(kDebugScript, "Opcode %d: Snake box init", op);

	_snakeBox = static_cast<MystResourceType6 *>(_invokingResource);
}
Esempio n. 12
0
void Mechanical::o_crystalLeaveRed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	debugC(kDebugScript, "Opcode %d: Crystal leave", op);

	_crystalLit = 0;
	_vm->redrawArea(22);
}
Esempio n. 13
0
void Mechanical::o_crystalEnterRed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	debugC(kDebugScript, "Opcode %d: Crystal enter", op);

	_crystalLit = 2;
	_vm->redrawArea(22);
}
Esempio n. 14
0
void Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	debugC(kDebugScript, "Opcode %d: Myst book staircase video", op);

	_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("sstairs", kMechanicalStack), 199, 108);
}
Esempio n. 15
0
void FontRenderer::setFont(Animation *font) {
	debugC(5, kDebugFont, "setFont(font)");

	_currentFont = font;
}
Esempio n. 16
0
void VDXPlayer::getStill(Common::ReadStream *in) {
	uint16 numXTiles = in->readUint16LE();
	debugC(5, kDebugVideo, "Groovie::VDX: numXTiles=%d", numXTiles);
	uint16 numYTiles = in->readUint16LE();
	debugC(5, kDebugVideo, "Groovie::VDX: numYTiles=%d", numYTiles);

	// It's skipped in the original:
	uint16 colorDepth = in->readUint16LE();
	debugC(5, kDebugVideo, "Groovie::VDX: colorDepth=%d", colorDepth);

	uint16 imageWidth = TILE_SIZE * numXTiles;

	uint8 mask = 0;
	byte *buf;
	if (_flagOne) {
		// Paint to the foreground
		buf = (byte *)_fg->getPixels();
		if (_flag2Byte) {
			mask = 0xff;
		} else {
			mask = 0;
		}

		// TODO: Verify this is the right procedure. Couldn't find it on the
		// disassembly, but it's required to work properly
		_flagFirstFrame = true;
	} else {
		// Paint to the background
		buf = (byte *)_bg->getPixels();
	}

	// Read the palette
	in->read(_palBuf, 3 * 256);

	if (_flagSeven) {
		_flagFive = true;
	}

	// Skip the frame when flag 5 is set, unless flag 1 is set
	if (!_flagFive || _flagOne) {

		byte colors[16];
		for (uint16 j = 0; j < numYTiles; j++) {
			byte *currentTile = buf + j * TILE_SIZE * imageWidth;
			for (uint16 i = numXTiles; i; i--) {
				uint8 color1 = in->readByte();
				uint8 color0 = in->readByte();
				uint16 colorMap = in->readUint16LE();
				expandColorMap(colors, colorMap, color1, color0);
				decodeBlockStill(currentTile, colors, 640, mask);

				currentTile += TILE_SIZE;
			}
		}

		// Apply the palette
		if (_flagNine) {
			// Flag 9 starts a fade in
			fadeIn(_palBuf);
		} else {
			if (!_flagOne && !_flagSeven) {
				// Actually apply the palette
				setPalette(_palBuf);
			}
		}

		if (!_flagOne) {
			_vm->_graphicsMan->updateScreen(_bg);
		}
		/*
		if (_flagSix) {
			if (_flagOne) {
				_vm->_graphicsMan->updateScreen(_fg);
			} else {
				_vm->_graphicsMan->updateScreen(_bg);
			}
			_flagSix = 0;
		}
		*/
	} else {
		// Skip the remaining data
		debugC(10, kDebugVideo, "Groovie::VDX: Skipping still frame");
		while (!in->eos()) {
			in->readByte();
		}
	}
}
Esempio n. 17
0
void FontRenderer::renderMultiLineText(int16 x, int16 y, const Common::String &origText, int32 mode) {
	debugC(5, kDebugFont, "renderMultiLineText(%d, %d, %s, %d)", x, y, origText.c_str(), mode);

	// divide the text in several lines
	// based on number of characters or size of lines.
	byte text[1024];
	Common::strlcpy((char *)text, origText.c_str(), 1024);

	byte *lines[16];
	int32 lineSize[16];
	int32 numLines = 0;

	byte *it = text;

	int16 maxWidth = 0;
	int16 curWidth = 0;

	while (true) {
		byte *lastLine = it;
		byte *lastSpace = it;
		int32 lastSpaceX = 0;
		int32 curLetterNr = 0;
		curWidth = 0;

		while (*it && curLetterNr < 50 && curWidth < 580) {
			byte curChar = *it;
			if (curChar == 32) {
				lastSpace = it;
				lastSpaceX = curWidth;
			} else
				curChar = textToFont(curChar);

			int width = _currentFont->getFrameWidth(curChar);
			curWidth += MAX(width - 2, 0);
			it++;
			curLetterNr++;
		}

		if (*lastLine == 0)
			break;

		lines[numLines] = lastLine;

		if (*it == 0)
			lineSize[numLines] = curWidth;
		else
			lineSize[numLines] = lastSpaceX;

		if (lineSize[numLines] > maxWidth)
			maxWidth = lineSize[numLines];

		lastLine = lastSpace + 1;
		numLines++;

		if (*it == 0)
			break;

		it = lastLine;
		*lastSpace = 0;

		if (numLines >= 16)
			break;
	}

	if (curWidth > maxWidth) {
		maxWidth = curWidth;
	}
	//numLines++;

	// get font height (assumed to be constant)
	int16 height = _currentFont->getHeight();
	int32 textSize = (height - 2) * numLines;
	y = y - textSize;
	if (y < 30)
		y = 30;
	if (y + textSize > 370)
		y = 370 - textSize;

	x -= _vm->state()->_currentScrollValue;

	// adapt x
	if (x - 30 - maxWidth / 2 < 0)
		x = maxWidth / 2 + 30;

	if (x + 30 + (maxWidth / 2) > TOON_SCREEN_WIDTH)
		x = TOON_SCREEN_WIDTH - (maxWidth / 2) - 30;

	// we have good coordinates now, we can render the multi line
	int16 curX = x;
	int16 curY = y;

	for (int32 i = 0; i < numLines; i++) {
		const byte *line = lines[i];
		curX = x - lineSize[i] / 2;
		_vm->addDirtyRect(curX + _vm->state()->_currentScrollValue, curY, curX + lineSize[i] + _vm->state()->_currentScrollValue + 2, curY + height);

		while (*line) {
			byte curChar = textToFont(*line);
			if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
			curX = curX + MAX<int32>(_currentFont->getFrameWidth(curChar) - 2, 0);
			//height = MAX(height, _currentFont->getFrameHeight(curChar));
			line++;
		}
		curY += height;
	}
}
Esempio n. 18
0
uint16 VDXPlayer::loadInternal() {
	if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
		int8 i;
		debugN(1, "Groovie::VDX: New VDX: bitflags are ");
		for (i = 15; i >= 0; i--) {
			debugN(1, "%d", _flags & (1 << i)? 1 : 0);
			if (i % 4 == 0) {
				debugN(1, " ");
			}
		}
		debug(1, " <- 0 ");
	}
	// Flags:
	// - 1 Puzzle piece? Skip palette, don't redraw full screen, draw still to b/ack buffer
	// - 2 Transparent color is 0xFF
	// - 5 Skip still chunks
	// - 7
	// - 8 Just show the first frame
	// - 9 Start a palette fade in
	_flagZero =		((_flags & (1 << 0)) != 0);
	_flagOne =		((_flags & (1 << 1)) != 0);
	_flag2Byte =	(_flags & (1 << 2)) ? 0xFF : 0x00;
	_flagThree =	((_flags & (1 << 3)) != 0);
	_flagFour =		((_flags & (1 << 4)) != 0);
	_flagFive =		((_flags & (1 << 5)) != 0);
	_flagSix =		((_flags & (1 << 6)) != 0);
	_flagSeven =	((_flags & (1 << 7)) != 0);
	_flagEight =	((_flags & (1 << 8)) != 0);
	_flagNine =		((_flags & (1 << 9)) != 0);

	// Enable highspeed if we're not obeying fps, and not marked as special
	// This will be disabled in chunk audio if we're actually an audio vdx
	if (_vm->_modeSpeed == kGroovieSpeedFast && ((_flags & (1 << 15)) == 0))
		setOverrideSpeed(true);

	if (_flagOnePrev && !_flagOne && !_flagEight) {
		_flagSeven = true;
	}

	// Save _flagOne for the next video
	_flagOnePrev = _flagOne;

	//_flagTransparent =	_flagOne;
	_flagFirstFrame =	_flagEight;
	//_flagSkipPalette =	_flagSeven;
	_flagSkipPalette =	false;
	//_flagSkipStill =	_flagFive || _flagSeven;
	//_flagUpdateStill =	_flagNine || _flagSix;

	// Begin reading the file
	debugC(1, kDebugVideo, "Groovie::VDX: Playing video");

	if (_file->readUint16LE() != VDX_IDENT) {
		error("Groovie::VDX: This does not appear to be a 7th guest VDX file");
		return 0;
	} else {
		debugC(5, kDebugVideo, "Groovie::VDX: VDX file identified correctly");
	}

	uint16 tmp;

	// Skip unknown data: 6 bytes, ref Martine
	tmp = _file->readUint16LE();
	debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine1 = 0x%04X", tmp);
	tmp = _file->readUint16LE();
	debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine2 = 0x%04X", tmp);
	tmp = _file->readUint16LE();
	debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine3 (FPS?) = %d", tmp);

	return tmp;
}
Esempio n. 19
0
void LegacySoundArchive::openArchive(const char *path) {
	// Close previously opened archive (if any)
	closeArchive();

	debugCN(1, kDraciArchiverDebugLevel, "Loading samples %s: ", path);

	_f = new Common::File();
	_f->open(path);
	if (_f->isOpen()) {
		debugC(1, kDraciArchiverDebugLevel, "Success");
	} else {
		debugC(1, kDraciArchiverDebugLevel, "Error");
		delete _f;
		_f = NULL;
		return;
	}

	// Save path for reading in files later on
	_path = path;

	// Read archive header
	debugC(1, kDraciArchiverDebugLevel, "Loading header");

	uint totalLength = _f->readUint32LE();
	const uint kMaxSamples = 4095;	// The no-sound file is exactly 16K bytes long, so don't fail on short reads
	uint sampleStarts[kMaxSamples];
	for (uint i = 0; i < kMaxSamples; ++i) {
		sampleStarts[i] = _f->readUint32LE();
	}

	// Fill the sample table
	for (_sampleCount = 0; _sampleCount < kMaxSamples - 1; ++_sampleCount) {
		int length = sampleStarts[_sampleCount + 1] - sampleStarts[_sampleCount];
		if (length <= 0 && sampleStarts[_sampleCount] >= totalLength)	// heuristics to detect the last sample
			break;
	}
	if (_sampleCount > 0) {
		debugC(1, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length",
			_sampleCount, totalLength);
		_samples = new SoundSample[_sampleCount];
		for (uint i = 0; i < _sampleCount; ++i) {
			_samples[i]._offset = sampleStarts[i];
			_samples[i]._length = sampleStarts[i+1] - sampleStarts[i];
			_samples[i]._frequency = 0;	// set in getSample()
		}
		if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength &&
		    _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) {
			// WORKAROUND: the stored length is stored with the header for sounds and without the hader for dubbing.  Crazy.
			debugC(1, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d",
				_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length,
				totalLength);
			closeArchive();
			return;
		}
	} else {
		debugC(1, kDraciArchiverDebugLevel, "Archive info: empty");
	}

	// Indicate that the archive has been successfully opened
	_opened = true;
}
Esempio n. 20
0
int32 CharacterDrew::getRandomIdleAnim() {
    debugC(3, kDebugCharacter, "getRandomIdleAnim()");

    static const int32 idle[] = { 6, 9, 10, 11, 12 };
    return idle[_vm->randRange(0, 4)];
}
Esempio n. 21
0
/**
 * Set the new screen number into the hero object and any carried objects
 */
void HugoEngine::setNewScreen(const int screenNum) {
	debugC(1, kDebugEngine, "setNewScreen(%d)", screenNum);

	*_screenPtr = screenNum;                        // HERO object
	_object->setCarriedScreen(screenNum);           // Carried objects
}
Esempio n. 22
0
/**
 * Process required action for inventory
 * Returns objId under cursor (or -1) for INV_GET
 */
int16 InventoryHandler::processInventory(const InvAct action, ...) {
	debugC(1, kDebugInventory, "processInventory(InvAct action, ...)");

	int16 imageNumb;                                // Total number of inventory items
	int displayNumb;                                // Total number displayed/carried
	// Compute total number and number displayed, i.e. number carried
	for (imageNumb = 0, displayNumb = 0; imageNumb < _maxInvent && _invent[imageNumb] != -1; imageNumb++) {
		if (_vm->_object->isCarried(_invent[imageNumb]))
			displayNumb++;
	}

	// Will we need the scroll arrows?
	bool scrollFl = displayNumb > kMaxDisp;
	va_list marker;                                 // Args used for D_ADD operation
	int16 cursorx, cursory;                         // Current cursor position
	int16 objId = -1;                               // Return objid under cursor

	switch (action) {
	case kInventoryActionInit:                      // Initialize inventory display
		constructInventory(imageNumb, displayNumb, scrollFl, _firstIconId);
		break;
	case kInventoryActionLeft:                      // Scroll left by one icon
		_firstIconId = MAX(0, _firstIconId - 1);
		constructInventory(imageNumb, displayNumb, scrollFl, _firstIconId);
		break;
	case kInventoryActionRight:                     // Scroll right by one icon
		_firstIconId = MIN(displayNumb, _firstIconId + 1);
		constructInventory(imageNumb, displayNumb, scrollFl, _firstIconId);
		break;
	case kInventoryActionGet:                       // Return object id under cursor
		// Get cursor position from variable argument list
		va_start(marker, action);                   // Initialize variable arguments
		cursorx = va_arg(marker, int);              // Cursor x
		cursory = va_arg(marker, int);              // Cursor y
		va_end(marker);                             // Reset variable arguments

		cursory -= kDibOffY;                        // Icon bar is at true zero
		if (cursory > 0 && cursory < kInvDy) {      // Within icon bar?
			int16 i = cursorx / kInvDx;             // Compute icon index
			if (scrollFl) {                         // Scroll buttons displayed
				if (i == 0) {                       // Left scroll button
					objId = kLeftArrow;
				} else {
					if (i == kMaxDisp - 1)          // Right scroll button
						objId = kRightArrow;
					else                            // Adjust for scroll
						i += _firstIconId - 1;      // i is icon index
				}
			}

			// If not an arrow, find object id - limit to valid range
			if (objId == -1 && i < displayNumb) {
				// Find objid by counting # carried objects == i+1
				int16 j;
				for (j = 0, i++; i > 0 && j < _vm->_object->_numObj; j++) {
					if (_vm->_object->isCarried(j)) {
						if (--i == 0)
							objId = j;
					}
				}
			}
		}
		break;
	}
	return objId;                                   // For the INV_GET action
}
Esempio n. 23
0
void AgiEngine::initialize() {
	// TODO: Some sound emulation modes do not fit our current music
	//       drivers, and I'm not sure what they are. For now, they might
	//       as well be called "PC Speaker" and "Not PC Speaker".

	// If used platform is Apple IIGS then we must use Apple IIGS sound emulation
	// because Apple IIGS AGI games use only Apple IIGS specific sound resources.
	if (getPlatform() == Common::kPlatformApple2GS) {
		_soundemu = SOUND_EMU_APPLE2GS;
	} else if (getPlatform() == Common::kPlatformCoCo3) {
		_soundemu = SOUND_EMU_COCO3;
	} else if (ConfMan.get("music_driver") == "auto") {
		// Default sound is the proper PCJr emulation
		_soundemu = SOUND_EMU_PCJR;
	} else {
		switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK|MDT_AMIGA|MDT_ADLIB|MDT_PCJR|MDT_MIDI))) {
		case MT_PCSPK:
			_soundemu = SOUND_EMU_PC;
			break;
		case MT_ADLIB:
			_soundemu = SOUND_EMU_NONE;
			break;
		case MT_PCJR:
			_soundemu = SOUND_EMU_PCJR;
			break;
		case MT_AMIGA:
			_soundemu = SOUND_EMU_AMIGA;
			break;
		default:
			debug(0, "DEF");
			_soundemu = SOUND_EMU_MIDI;
			break;
		}
	}

	initRenderMode();

	_buttonStyle = AgiButtonStyle(_renderMode);
	_defaultButtonStyle = AgiButtonStyle();
	_console = new Console(this);
	_gfx = new GfxMgr(this);
	_sound = new SoundMgr(this, _mixer);
	_picture = new PictureMgr(this, _gfx);
	_sprites = new SpritesMgr(this, _gfx);

	_gfx->initMachine();

	_game.gameFlags = 0;

	_game.colorFg = 15;
	_game.colorBg = 0;

	_game.name[0] = '\0';

	_game.sbufOrig = (uint8 *)calloc(_WIDTH, _HEIGHT * 2); // Allocate space for two AGI screens vertically
	_game.sbuf16c  = _game.sbufOrig + SBUF16_OFFSET; // Make sbuf16c point to the 16 color (+control line & priority info) AGI screen
	_game.sbuf256c = _game.sbufOrig + SBUF256_OFFSET; // Make sbuf256c point to the 256 color AGI screen
	_game.sbuf     = _game.sbuf16c; // Make sbuf point to the 16 color (+control line & priority info) AGI screen by default

	_gfx->initVideo();

	_lastSaveTime = 0;

	_lastTick = _system->getMillis();

	debugC(2, kDebugLevelMain, "Detect game");

	if (agiDetectGame() == errOK) {
		_game.state = STATE_LOADED;
		debugC(2, kDebugLevelMain, "game loaded");
	} else {
		warning("Could not open AGI game");
	}

	debugC(2, kDebugLevelMain, "Init sound");
}
Esempio n. 24
0
/**
 * Process inventory state machine
 */
void InventoryHandler::runInventory() {
	Status &gameStatus = _vm->getGameStatus();

	debugC(1, kDebugInventory, "runInventory");

	switch (_inventoryState) {
	case kInventoryOff:                             // Icon bar off screen
		break;
	case kInventoryUp:                              // Icon bar moving up
		_inventoryHeight -= kStepDy;                // Move the icon bar up
		if (_inventoryHeight <= 0)                  // Limit travel
			_inventoryHeight = 0;

		// Move visible portion to _frontBuffer, restore uncovered portion, display results
		_vm->_screen->moveImage(_vm->_screen->getIconBuffer(), 0, 0, kXPix, _inventoryHeight, kXPix, _vm->_screen->getFrontBuffer(), 0, kDibOffY, kXPix);
		_vm->_screen->moveImage(_vm->_screen->getBackBufferBackup(), 0, _inventoryHeight + kDibOffY, kXPix, kStepDy, kXPix, _vm->_screen->getFrontBuffer(), 0, _inventoryHeight + kDibOffY, kXPix);
		_vm->_screen->displayRect(0, kDibOffY, kXPix, _inventoryHeight + kStepDy);

		if (_inventoryHeight == 0) {                // Finished moving up?
			// Yes, restore dibs and exit back to game state machine
			_vm->_screen->moveImage(_vm->_screen->getBackBufferBackup(), 0, 0, kXPix, kYPix, kXPix, _vm->_screen->getBackBuffer(), 0, 0, kXPix);
			_vm->_screen->moveImage(_vm->_screen->getBackBuffer(), 0, 0, kXPix, kYPix, kXPix, _vm->_screen->getFrontBuffer(), 0, 0, kXPix);
			_vm->_object->updateImages();           // Add objects back into display list for restore
			_inventoryState = kInventoryOff;
			gameStatus._viewState = kViewPlay;
		}
		break;
	case kInventoryDown:                            // Icon bar moving down
		// If this is the first step, initialize dib_i
		// and get any icon/text out of _frontBuffer
		if (_inventoryHeight == 0) {
			processInventory(kInventoryActionInit); // Initialize dib_i
			_vm->_screen->displayList(kDisplayRestore); // Restore _frontBuffer
			_vm->_object->updateImages();           // Rebuild _frontBuffer without icons/text
			_vm->_screen->displayList(kDisplayDisplay); // Blit display list to screen
		}

		_inventoryHeight += kStepDy;                // Move the icon bar down
		if (_inventoryHeight > kInvDy)              // Limit travel
			_inventoryHeight = kInvDy;

		// Move visible portion to _frontBuffer, display results
		_vm->_screen->moveImage(_vm->_screen->getIconBuffer(), 0, 0, kXPix, _inventoryHeight, kXPix, _vm->_screen->getFrontBuffer(), 0, kDibOffY, kXPix);
		_vm->_screen->displayRect(0, kDibOffY, kXPix, _inventoryHeight);

		if (_inventoryHeight == kInvDy) {           // Finished moving down?
			// Yes, prepare view dibs for special inventory display since
			// we can't refresh objects while icon bar overlayed...
			// 1. Save backing store _backBuffer in temporary dib_c
			// 2. Make snapshot of _frontBuffer the new _backBuffer backing store
			// 3. Reset the display list
			_vm->_screen->moveImage(_vm->_screen->getBackBuffer(), 0, 0, kXPix, kYPix, kXPix, _vm->_screen->getBackBufferBackup(), 0, 0, kXPix);
			_vm->_screen->moveImage(_vm->_screen->getFrontBuffer(), 0, 0, kXPix, kYPix, kXPix, _vm->_screen->getBackBuffer(), 0, 0, kXPix);
			_vm->_screen->displayList(kDisplayInit);
			_inventoryState = kInventoryActive;
		}
		break;
	case kInventoryActive:                          // Inventory active
		_vm->_parser->charHandler();                // Still allow commands
		_vm->_screen->displayList(kDisplayRestore); // Restore previous background
		_vm->_screen->displayList(kDisplayDisplay); // Blit the display list to screen
		break;
	}
}
Esempio n. 25
0
// Save game
void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
	if (getState()->scene <= kSceneIntro)
		return;

	// Validate main header
	SavegameMainHeader header;
	if (!loadMainHeader(_savegame, &header)) {
		debugC(2, kLastExpressDebugSavegame, "SaveLoad::saveGame - Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
		return;
	}

	if (!_savegame)
		error("SaveLoad::saveGame: savegame stream is invalid");

	// Validate the current entry if it exists
	if (header.count > 0) {
		_savegame->seek(header.offsetEntry);

		// Load entry header
		SavegameEntryHeader entry;
		Common::Serializer ser(_savegame, NULL);
		entry.saveLoadWithSerializer(ser);

		if (!entry.isValid()) {
			warning("SaveLoad::saveGame: Invalid entry. This savegame might be corrupted!");
			_savegame->seek(header.offset);
		} else if (getState()->time < entry.time || (type == kSavegameTypeTickInterval && getState()->time == entry.time)) {
			// Not ready to save a game, skipping!
			return;
		} else if ((type == kSavegameTypeTime || type == kSavegameTypeEvent)
			&& (entry.type == kSavegameTypeTickInterval && (getState()->time - entry.time) < 450)) {
			_savegame->seek(header.offsetEntry);
			--header.count;
		} else {
			_savegame->seek(header.offset);
		}
	} else {
		// Seek to the next savegame entry
		_savegame->seek(header.offset);
	}

	if (type != kSavegameTypeEvent2 && type != kSavegameTypeAuto)
		header.offsetEntry = (uint32)_savegame->pos();

	// Write the savegame entry
	writeEntry(type, entity, value);

	if (!header.keepIndex)
		++header.count;

	if (type == kSavegameTypeEvent2 || type == kSavegameTypeAuto) {
		header.keepIndex = 1;
	} else {
		header.keepIndex = 0;
		header.offset = (uint32)_savegame->pos();

		// Save ticks
		_gameTicksLastSavegame = getState()->timeTicks;
	}

	// Validate the main header
	if (!header.isValid())
		error("SaveLoad::saveGame: main game header is invalid!");

	// Write the main header
	_savegame->seek(0);
	Common::Serializer ser(NULL, _savegame);
	header.saveLoadWithSerializer(ser);

	flushStream(getMenu()->getGameId());
}
Esempio n. 26
0
void SmushFont::drawStringWrap(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right, bool center) {
	debugC(DEBUG_SMUSH, "SmushFont::drawStringWrap(%s, %d, %d, %d, %d, %d)", str, x, y, left, right, center);

	const int width = right - left;
	char *s = strdup(str);
	char *words[MAX_WORDS];
	int word_count = 0;

	char *tmp = s;
	while (tmp) {
		assert(word_count < MAX_WORDS);
		words[word_count++] = tmp;
		tmp = strpbrk(tmp, " \t\r\n");
		if (tmp == 0)
			break;
		*tmp++ = 0;
	}

	int i = 0, max_width = 0, height = 0, line_count = 0;

	char *substrings[MAX_WORDS];
	int substr_widths[MAX_WORDS];
	const int space_width = getCharWidth(' ');

	i = 0;
	while (i < word_count) {
		char *substr = words[i++];
		int substr_width = getStringWidth(substr);

		while (i < word_count) {
			int word_width = getStringWidth(words[i]);
			if ((substr_width + space_width + word_width) >= width)
				break;
			substr_width += word_width + space_width;
			*(words[i]-1) = ' ';	// Convert 0 byte back to space
			i++;
		}

		substrings[line_count] = substr;
		substr_widths[line_count++] = substr_width;
		if (max_width < substr_width)
			max_width = substr_width;
		height += getStringHeight(substr);
	}

	if (y > dst_height - height) {
		y = dst_height - height;
	}

	if (center) {
		max_width = (max_width + 1) / 2;
		x = left + width / 2;

		if (x < left + max_width)
			x = left + max_width;
		if (x > right - max_width)
			x = right - max_width;

		for (i = 0; i < line_count; i++) {
			drawSubstring(substrings[i], buffer, dst_width, x - substr_widths[i] / 2, y);
			y += getStringHeight(substrings[i]);
		}
	} else {
		if (x > dst_width - max_width)
			x = dst_width - max_width;

		for (i = 0; i < line_count; i++) {
			drawSubstring(substrings[i], buffer, dst_width, x, y);
			y += getStringHeight(substrings[i]);
		}
	}

	free(s);
}
Esempio n. 27
0
void PreAgiEngine::initialize() {
	// TODO: Some sound emulation modes do not fit our current music
	//       drivers, and I'm not sure what they are. For now, they might
	//       as well be called "PC Speaker" and "Not PC Speaker".

	switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) {
	case MT_PCSPK:
		_soundemu = SOUND_EMU_PC;
		break;
	default:
		_soundemu = SOUND_EMU_NONE;
		break;
	}

	if (ConfMan.hasKey("render_mode")) {
		_renderMode = Common::parseRenderMode(ConfMan.get("render_mode").c_str());
	} else if (ConfMan.hasKey("platform")) {
		switch (Common::parsePlatform(ConfMan.get("platform"))) {
		case Common::kPlatformAmiga:
			_renderMode = Common::kRenderAmiga;
			break;
		case Common::kPlatformPC:
			_renderMode = Common::kRenderEGA;
			break;
		default:
			_renderMode = Common::kRenderEGA;
			break;
		}
	}

	_gfx = new GfxMgr(this);
	//_sound = new SoundMgr(this, _mixer);
	_picture = new PictureMgr(this, _gfx);
	//_sprites = new SpritesMgr(this, _gfx);

	_gfx->initMachine();

	_game.gameFlags = 0;

	_game.colorFg = 15;
	_game.colorBg = 0;

	_defaultColor = 0xF;

	_game.name[0] = '\0';

	_game.sbufOrig = (uint8 *)calloc(_WIDTH, _HEIGHT * 2); // Allocate space for two AGI screens vertically
	_game.sbuf16c  = _game.sbufOrig + SBUF16_OFFSET; // Make sbuf16c point to the 16 color (+control line & priority info) AGI screen
	_game.sbuf     = _game.sbuf16c; // Make sbuf point to the 16 color (+control line & priority info) AGI screen by default

	_game.lineMinPrint = 0; // hardcoded

	_gfx->initVideo();
	//_sound->initSound();

	_speakerStream = new Audio::PCSpeaker(_mixer->getOutputRate());
	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
							_speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);

	debugC(2, kDebugLevelMain, "Detect game");

	// clear all resources and events
	for (int i = 0; i < MAX_DIRS; i++) {
		memset(&_game.pictures[i], 0, sizeof(struct AgiPicture));
		memset(&_game.sounds[i], 0, sizeof(class AgiSound *)); // _game.sounds contains pointers now
		memset(&_game.dirPic[i], 0, sizeof(struct AgiDir));
		memset(&_game.dirSound[i], 0, sizeof(struct AgiDir));
	}

	debugC(2, kDebugLevelMain, "Init sound");
}
Esempio n. 28
0
void Surface::wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines) {
	debugC(ERROR_INTERMEDIATE, kLureDebugStrings, "wordWrap(text=%s, width=%d", text, width);
	numLines = 1;
	uint16 lineWidth = 0;
	char *s;
	bool newLine;

	s = text;

	// Scan through the text and insert NULLs to break the line into allowable widths

	while (*s != '\0') {
		char *wordStart = s;
		while (*wordStart == ' ') ++wordStart;
		char *wordEnd = strchr(wordStart, ' ');
		char *wordEnd2 = strchr(wordStart, '\n');
		if ((!wordEnd) || ((wordEnd2) && (wordEnd2 < wordEnd))) {
			wordEnd = wordEnd2;
			newLine = (wordEnd2 != NULL);
		} else {
			newLine = false;
		}

		debugC(ERROR_DETAILED, kLureDebugStrings, "word scanning: start=%xh, after=%xh, newLine=%d",
			(uint32)(wordStart - text), (uint32)((wordEnd == NULL) ? -1 : wordEnd - text), newLine ? 1 : 0);

		if (wordEnd) {
			if (*wordEnd != '\0') --wordEnd;
		} else {
			wordEnd = strchr(wordStart, '\0') - 1;
		}

		int wordBytes = (int) (wordEnd - s + 1);
		uint16 wordSize = (wordBytes == 0) ? 0 : textWidth(s, wordBytes);
		if (gDebugLevel >= ERROR_DETAILED) {
			char wordBuffer[MAX_DESC_SIZE];
			strncpy(wordBuffer, wordStart, wordBytes);
			wordBuffer[wordBytes] = '\0';
			debugC(ERROR_DETAILED, kLureDebugStrings, "word='%s', size=%d", wordBuffer, wordSize);
		}

		if (lineWidth + wordSize > width) {
			// Break word onto next line
			*(wordStart - 1) = '\0';
			++numLines;
			lineWidth = 0;
			wordEnd = wordStart - 1;
		} else if (newLine) {
			// Break on newline
			++numLines;
			*++wordEnd = '\0';
			lineWidth = 0;
		} else {
			// Add word's length to total for line
			lineWidth += wordSize;
		}

		s = wordEnd+1;
	}

	// Set up a list for the start of each line
	lines = (char **) Memory::alloc(sizeof(char *) * numLines);
	lines[0] = text;
	debugC(ERROR_DETAILED, kLureDebugStrings, "wordWrap lines[0]='%s'", lines[0]);
	for (int ctr = 1; ctr < numLines; ++ctr) {
		lines[ctr] = strchr(lines[ctr-1], 0) + 1;
		debugC(ERROR_DETAILED, kLureDebugStrings, "wordWrap lines[%d]='%s'", ctr, lines[ctr]);
	}

	debugC(ERROR_INTERMEDIATE, kLureDebugStrings, "wordWrap end - numLines=%d", numLines);
}
Esempio n. 29
0
bool AgiEngine::predictiveDialog(void) {
	int key = 0, active = -1, lastactive = 0;
	bool rc = false;
	uint8 x;
	int y;
	int bx[17], by[17];
	String prefix;
	char temp[MAXWORDLEN + 1], repeatcount[MAXWORDLEN];
	AgiBlock tmpwindow;
	bool navigationwithkeys = false;
	bool processkey;

	const char *buttonStr[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
	const char *buttons[] = {
		"(1)'-.&",  "(2)abc", "(3)def",
		"(4)ghi",  "(5)jkl", "(6)mno",
		"(7)pqrs", "(8)tuv", "(9)wxyz",
		"(#)next",    "add",
		"<",
		"Cancel",  "OK",
		"Pre", "(0) ", NULL
	};
	const int colors[] = {
		15, 0, 15, 0, 15, 0,
		15, 0, 15, 0, 15, 0,
		15, 0, 15, 0, 15, 0,
		15, 12, 15, 12,
		15, 0,
		15, 0, 15, 0,
		14, 0, 15, 0, 0, 0
	};
	const char *modes[] = { "(*)Pre", "(*)123", "(*)Abc" };

	// FIXME: Move this to a more appropriate place.
	if (!_predictiveDictText) {
		loadDict();
		if (!_predictiveDictText)
			return false;
	}
	_predictiveDictActLine = NULL;
	uint8 numMatchingWords = 0;

	_predictiveDialogRunning = true;
	_system->setFeatureState(OSystem::kFeatureDisableKeyFiltering, true);

	memset(repeatcount, 0, MAXWORDLEN);

	// show the predictive dialog.
	// if another window is already in display, save its state into tmpwindow
	memset(&tmpwindow, 0, sizeof(tmpwindow));
	tmpwindow.active = false;
	if (_game.window.active)
		memcpy(&tmpwindow, &(_game.window), sizeof(AgiBlock));
	drawWindow(50, 40, 269, 159);
	_gfx->drawRectangle(62, 54, 249, 66, MSG_BOX_TEXT);
	_gfx->flushBlock(62, 54, 249, 66);

	bx[15] = 73; // Zero/space
	by[15] = 120;
	bx[9] = 110; // next
	by[9] = 120;
	bx[10] = 172; // add
	by[10] = 120;
	bx[14] = 200; // Mode
	by[14] = 120;
	bx[11] = 252; // Backspace
	by[11] = 57;
	bx[12] = 180; // Cancel
	by[12] = 140;
	bx[13] = 240; // OK
	by[13] = 140;

	x = 73;
	y = 75;
	for (int i = 0; i < 9; i++) {
		bx[i] = x;
		by[i] = y;
		x += 60;
		if (i % 3 == 2) {
			y += 15;
			x = 73;
		}
	}

	clearKeyQueue();

	prefix.clear();
	_currentCode.clear();
	_currentWord.clear();
	_wordNumber = 0;

	int mode = kModePre;

	bool needRefresh = true;

	for (;;) {
		if (needRefresh) {
			for (int i = 0; buttons[i]; i++) {
				int color1 = colors[i * 2];
				int color2 = colors[i * 2 + 1];

				if (i == 9 && !((mode != kModeAbc && _predictiveDictActLine && numMatchingWords > 1)
							|| (mode == kModeAbc && _currentWord.size() && _currentWord.lastChar() != ' '))) { // Next
					color2 = 7;
				}

				// needs fixing, or remove it!
				bool _addIsActive = false; // FIXME: word adding is not implemented
				if (i == 10 && !_addIsActive) { // Add
					color2 = 7;
				}
				if (i == 14) {
					_gfx->drawDefaultStyleButton(bx[i], by[i], modes[mode], i == active, 0, color1, color2);
				} else {
					_gfx->drawDefaultStyleButton(bx[i], by[i], buttons[i], i == active, 0, color1, color2);
				}
			}

			temp[MAXWORDLEN] = 0;

			strncpy(temp, prefix.c_str(), MAXWORDLEN);
			strncat(temp, _currentWord.c_str(), MAXWORDLEN);

			for (int i = prefix.size() + _currentCode.size(); i < MAXWORDLEN; i++)
				temp[i] = ' ';

			printText(temp, 0, 8, 7, MAXWORDLEN, 15, 0);
			_gfx->flushBlock(62, 54, 249, 66);

			if (active >= 0 && !navigationwithkeys) {
				// provide visual feedback only when not navigating with the arrows
				// so that the user can see the active button.
				active = -1;
				needRefresh = true;
			} else
				needRefresh = false;

			_gfx->doUpdate();
		}

		pollTimer();
		key = doPollKeyboard();
		processkey = false;
		switch (key) {
		case KEY_ENTER:
			if (navigationwithkeys) {
				// when the user has utilized arrow key navigation,
				// interpret enter as 'click' on the active button
				active = lastactive;
			} else {
				// else it is a shortcut for 'Ok'
				active = 13;
			}
			processkey = true;
			break;
		case KEY_ESCAPE:
			rc = false;
			goto getout;
		case BUTTON_LEFT:
			navigationwithkeys = false;
			for (int i = 0; buttons[i]; i++) {
				if (_gfx->testButton(bx[i], by[i], buttons[i])) {
					active = i;
					processkey = true;
					break;
				}
			}
			break;
		case KEY_BACKSPACE:
			active = 11;
			processkey = true;
			break;
		case '#':
			active = 9;
			processkey = true;
			break;
		case '*':
			active = 14;
			processkey = true;
			break;
		case 0x09:	// Tab
			navigationwithkeys = true;
			debugC(3, kDebugLevelText, "Focus change");
			lastactive = active = lastactive + 1;
			active %= ARRAYSIZE(buttons) - 1;
			needRefresh = true;
			break;
		case KEY_LEFT:
			navigationwithkeys = true;
			if (lastactive == 0 || lastactive == 3 || lastactive == 6)
				active = lastactive + 2;
			else if (lastactive == 9)
				active = 15;
			else if (lastactive == 11)
				active = 11;
			else if (lastactive == 12)
				active = 13;
			else if (lastactive == 14)
				active = 10;
			else
				active = lastactive - 1;
			lastactive = active;
			needRefresh = true;
			break;
		case KEY_RIGHT:
			navigationwithkeys = true;
			if (lastactive == 2 || lastactive == 5 || lastactive == 8)
				active = lastactive - 2;
			else if (lastactive == 10)
				active = 14;
			else if (lastactive == 11)
				active = 11;
			else if (lastactive == 13)
				active = 12;
			else if (lastactive == 15)
				active = 9;
			else
				active = lastactive + 1;
			lastactive = active;
			needRefresh = true;
			break;
		case KEY_UP:
			navigationwithkeys = true;
			if (lastactive <= 2)
				active = 11;
			else if (lastactive == 9 || lastactive == 10)
				active = lastactive - 2;
			else if (lastactive == 11)
				active = 13;
			else if (lastactive == 14)
				active = 8;
			else if (lastactive == 15)
				active = 6;
			else
				active = lastactive - 3;
			lastactive = active;
			needRefresh = true;
			break;
		case KEY_DOWN:
			navigationwithkeys = true;
			if (lastactive == 6)
				active = 15;
			else if (lastactive == 7 || lastactive == 8)
				active = lastactive + 2;
			else if (lastactive == 11)
				active = 0;
			else if (lastactive == 12 || lastactive == 13)
				active = 11;
			else if (lastactive == 14 || lastactive == 15)
				active = lastactive - 2;
			else
				active = lastactive + 3;
			lastactive = active;
			needRefresh = true;
			break;
		default:
			// handle numeric buttons
			if (key >= '1' && key <= '9') {
				active = key - '1';
				processkey = true;
			} else if (key == '0') {
				active = 15;
				processkey = true;
			}
			break;
		}

		if (processkey) {
			if (active >= 0) {
				needRefresh = true;
				lastactive = active;
				if (active == 15 && mode != kModeNum) { // Space
					// bring MRU word at the top of the list when changing words
					if (mode == kModePre && _predictiveDictActLine && numMatchingWords > 1 && _wordNumber != 0)
						bringWordtoTop(_predictiveDictActLine, _wordNumber);
					strncpy(temp, _currentWord.c_str(), _currentCode.size());
					temp[_currentCode.size()] = 0;
					prefix += temp;
					prefix += " ";
					_currentCode.clear();
					_currentWord.clear();
					numMatchingWords = 0;
					memset(repeatcount, 0, MAXWORDLEN);
				} else if (active < 9 || active == 11 || active == 15) { // number or backspace
					if (active == 11) { // backspace
						if (_currentCode.size()) {
							repeatcount[_currentCode.size() - 1] = 0;
							_currentCode.deleteLastChar();
						} else {
							if (prefix.size())
								prefix.deleteLastChar();
						}
					} else if (prefix.size() + _currentCode.size() < MAXWORDLEN - 1) { // don't overflow the dialog line
						if (active == 15) { // zero
							_currentCode += buttonStr[9];
						} else {
							_currentCode += buttonStr[active];
						}
					}

					switch (mode) {
					case kModeNum:
						_currentWord = _currentCode;
						break;
					case kModePre:
						if (!matchWord() && _currentCode.size()) {
							_currentCode.deleteLastChar();
							matchWord();
						}
						numMatchingWords = countWordsInString(_predictiveDictActLine);
						break;
					case kModeAbc:
						for (x = 0; x < _currentCode.size(); x++)
							if (_currentCode[x] >= '1')
								temp[x] = buttons[_currentCode[x] - '1'][3 + repeatcount[x]];
						temp[_currentCode.size()] = 0;
						_currentWord = temp;
					}
				} else if (active == 9) { // next
					if (mode == kModePre) {
						if (_predictiveDictActLine && numMatchingWords > 1) {
							_wordNumber = (_wordNumber + 1) % numMatchingWords;
							char tmp[MAXLINELEN];
							strncpy(tmp, _predictiveDictActLine, MAXLINELEN);
							char *tok = strtok(tmp, " ");
							for (uint8 i = 0; i <= _wordNumber; i++)
								tok = strtok(NULL, " ");
							_currentWord = String(tok, _currentCode.size());
						}
					} else if (mode == kModeAbc){
						x = _currentCode.size();
						if (x) {
							if (_currentCode.lastChar() == '1' || _currentCode.lastChar() == '7' || _currentCode.lastChar() == '9')
								repeatcount[x - 1] = (repeatcount[x - 1] + 1) % 4;
							else
								repeatcount[x - 1] = (repeatcount[x - 1] + 1) % 3;
							if (_currentCode.lastChar() >= '1')
								_currentWord.setChar(buttons[_currentCode[x - 1] - '1'][3 + repeatcount[x - 1]], x-1);
						}
					}
				} else if (active == 10) { // add
					debug(0, "add");
				} else if (active == 13) { // Ok
					// bring MRU word at the top of the list when ok'ed out of the dialog
					if (mode == kModePre && _predictiveDictActLine && numMatchingWords > 1 && _wordNumber != 0)
						bringWordtoTop(_predictiveDictActLine, _wordNumber);
					rc = true;
					goto press;
				} else if (active == 14) { // Mode
					mode++;
					if (mode > kModeAbc)
						mode = kModePre;

					// truncate current input at mode change
					strncpy(temp, _currentWord.c_str(), _currentCode.size());
					temp[_currentCode.size()] = 0;
					prefix += temp;
					_currentCode.clear();
					_currentWord.clear();
					memset(repeatcount, 0, MAXWORDLEN);
				} else {
					goto press;
				}
			}
		}
	}

 press:
	strncpy(_predictiveResult, prefix.c_str(), 40);
	strncat(_predictiveResult, _currentWord.c_str(), 40);
	_predictiveResult[prefix.size() + _currentCode.size() + 1] = 0;

 getout:
	// if another window was shown, bring it up again
	if (!tmpwindow.active)
		closeWindow();
	else {
		_gfx->restoreBlock(_game.window.x1, _game.window.y1,
				_game.window.x2, _game.window.y2, _game.window.buffer);

		free(_game.window.buffer);
		memcpy(&(_game.window), &tmpwindow, sizeof(AgiBlock));
		_gfx->doUpdate();
	}

	_system->setFeatureState(OSystem::kFeatureDisableKeyFiltering, false);
	_predictiveDialogRunning = false;

	return rc;
}
Esempio n. 30
0
void Mechanical::o_throneEnablePassage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
	debugC(kDebugScript, "Opcode %d: Enable throne passage", op);

	_vm->_resources[argv[0]]->setEnabled(getVar(var));
}