Ejemplo n.º 1
0
SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto)
	: ScriptingEffect(engine, key, SCRIPTING_EFFECT_AUDIO) {
	_syncto = syncto;
	_sub = NULL;

	Audio::RewindableAudioStream *audioStream = NULL;

	if (filename.contains(".wav")) {
		Common::File *file = new Common::File();
		if (_engine->getSearchManager()->openFile(*file, filename)) {
			audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
		}
	} else {
		audioStream = makeRawZorkStream(filename, _engine);
	}

	_engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream);

	Common::String subname = filename;
	subname.setChar('s', subname.size() - 3);
	subname.setChar('u', subname.size() - 2);
	subname.setChar('b', subname.size() - 1);

	if (_engine->getSearchManager()->hasFile(subname))
		_sub = new Subtitle(_engine, subname);
}
Ejemplo n.º 2
0
bool ActionStreamVideo::execute() {
	Video::VideoDecoder *decoder;
	Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1);
	Common::String subname = _fileName;
	subname.setChar('s', subname.size() - 3);
	subname.setChar('u', subname.size() - 2);
	subname.setChar('b', subname.size() - 1);
	bool subtitleExists = _engine->getSearchManager()->hasFile(subname);
	bool switchToHires = false;

// NOTE: We only show the hires MPEG2 videos when libmpeg2 is compiled in,
// otherwise we fall back to the lowres ones
#ifdef USE_MPEG2
	Common::String hiresFileName = _fileName;
	hiresFileName.setChar('d', hiresFileName.size() - 8);
	hiresFileName.setChar('v', hiresFileName.size() - 3);
	hiresFileName.setChar('o', hiresFileName.size() - 2);
	hiresFileName.setChar('b', hiresFileName.size() - 1);

	if (_engine->getScriptManager()->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) {
		// TODO: Enable once AC3 support is implemented
		if (!_engine->getSearchManager()->hasFile(_fileName))	// Check for the regular video
			return true;
		warning("The hires videos of the DVD version of ZGI aren't supported yet, using lowres");
		//_fileName = hiresFileName;
		//switchToHires = true;
	} else if (!_engine->getSearchManager()->hasFile(_fileName))
		return true;
#else
	if (!_engine->getSearchManager()->hasFile(_fileName))
		return true;
#endif

	decoder = _engine->loadAnimation(_fileName);
	Subtitle *sub = (subtitleExists) ? new Subtitle(_engine, subname, switchToHires) : NULL;

	_engine->getCursorManager()->showMouse(false);

	if (switchToHires) {
		_engine->initHiresScreen();
		destRect = Common::Rect(40, -40, 760, 440);
		Common::Rect workingWindow = _engine->_workingWindow;
		workingWindow.translate(0, -40);
		_engine->getRenderManager()->initSubArea(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT, workingWindow);
	}

	_engine->playVideo(*decoder, destRect, _skippable, sub);

	if (switchToHires) {
		_engine->initScreen();
		_engine->getRenderManager()->initSubArea(WINDOW_WIDTH, WINDOW_HEIGHT, _engine->_workingWindow);
	}

	_engine->getCursorManager()->showMouse(true);

	delete decoder;
	delete sub;

	return true;
}
Ejemplo n.º 3
0
Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) {
	Common::File *file = new Common::File();
	Common::String actualName = filePath;
	bool found = engine->getSearchManager()->openFile(*file, actualName);
	bool isRaw = actualName.hasSuffix(".raw");

	if ((!found && isRaw) || (found && isRaw && file->size() < 10)) {
		if (found)
			file->close();

		// Check for an audio patch (.src)
		actualName.setChar('s', actualName.size() - 3);
		actualName.setChar('r', actualName.size() - 2);
		actualName.setChar('c', actualName.size() - 1);

		if (!engine->getSearchManager()->openFile(*file, actualName))
			return NULL;
	} else if (!found && !isRaw) {
		return NULL;
	}

	// Get the file name
	Common::StringTokenizer tokenizer(actualName, "/\\");
	Common::String fileName;
	while (!tokenizer.empty()) {
		fileName = tokenizer.nextToken();
	}

	fileName.toLowercase();

	const SoundParams *soundParams = NULL;

	if (engine->getGameId() == GID_NEMESIS) {
		for (int i = 0; i < 32; ++i) {
			if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == (fileName[6]))
				soundParams = &RawZorkStream::_zNemSoundParamLookupTable[i];
		}
	} else if (engine->getGameId() == GID_GRANDINQUISITOR) {
		for (int i = 0; i < 24; ++i) {
			if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == (fileName[7]))
				soundParams = &RawZorkStream::_zgiSoundParamLookupTable[i];
		}
	}

	if (soundParams == NULL)
		return NULL;

	if (soundParams->packed) {
		return makeRawZorkStream(wrapBufferedSeekableReadStream(file, 2048, DisposeAfterUse::YES), soundParams->rate, soundParams->stereo, DisposeAfterUse::YES);
	} else {
		byte flags = 0;
		if (soundParams->bits16)
			flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
		if (soundParams->stereo)
			flags |= Audio::FLAG_STEREO;

		return Audio::makePCMStream(file, soundParams->rate, flags, DisposeAfterUse::YES);
	}
}
Ejemplo n.º 4
0
Common::String HiRes4Engine_Atari::formatNounError(const Common::String &verb, const Common::String &noun) const {
	Common::String err = _strings.nounError;
	for (uint i = 0; i < verb.size(); ++i)
		err.setChar(verb[i], i + 8);
	for (uint i = 0; i < noun.size(); ++i)
		err.setChar(noun[i], i + 19);
	return err;
}
Ejemplo n.º 5
0
bool Console::cmdDumpImage(int argc, const char **argv) {
	if (argc != 2) {
		debugPrintf("Use %s <TGA/TGZ name> to dump a Z-Vision TGA/TGZ image into a regular BMP image\n", argv[0]);
		return true;
	}

	Common::String fileName = argv[1];
	if (!fileName.hasSuffix(".tga")) {
		debugPrintf("%s is not an image file", argv[1]);
	}

	Common::File f;
	if (!_engine->getSearchManager()->openFile(f, argv[1])) {
		warning("File not found: %s", argv[1]);
		return true;
	}

	Graphics::Surface surface;
	_engine->getRenderManager()->readImageToSurface(argv[1], surface, false);

	// Open file
	Common::DumpFile out;

	fileName.setChar('b', fileName.size() - 3);
	fileName.setChar('m', fileName.size() - 2);
	fileName.setChar('p', fileName.size() - 1);

	out.open(fileName);

	// Write BMP header
	out.writeByte('B');
	out.writeByte('M');
	out.writeUint32LE(surface.h * surface.pitch + 54);
	out.writeUint32LE(0);
	out.writeUint32LE(54);
	out.writeUint32LE(40);
	out.writeUint32LE(surface.w);
	out.writeUint32LE(surface.h);
	out.writeUint16LE(1);
	out.writeUint16LE(16);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);

	// Write pixel data to BMP
	out.write(surface.getPixels(), surface.pitch * surface.h);

	out.flush();
	out.close();

	surface.free();

	return true;
}
Ejemplo n.º 6
0
void Inter_v6::probe16bitMusic(Common::String &fileName) {
	if (fileName[fileName.size() - 1] != '8')
		return;

	fileName.setChar('V', fileName.size() - 1);

	if (_vm->_dataIO->hasFile(fileName))
		return;

	fileName.setChar('8', fileName.size() - 1);
}
Ejemplo n.º 7
0
MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume)
	: MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) {
	_loop = loop;
	_volume = volume;
	_crossfade = false;
	_crossfadeTarget = 0;
	_crossfadeTime = 0;
	_attenuate = 0;
	_pantrack = false;
	_pantrackPosition = 0;
	_sub = NULL;
	_stereo = false;
	_loaded = false;

	Audio::RewindableAudioStream *audioStream = NULL;

	if (filename.contains(".wav")) {
		Common::File *file = new Common::File();
		if (_engine->getSearchManager()->openFile(*file, filename)) {
			audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
		}
	} else {
		audioStream = makeRawZorkStream(filename, _engine);
	}

	if (audioStream) {
		_stereo = audioStream->isStereo();

		if (_loop) {
			Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
			_engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume);
		} else {
			_engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume);
		}

		if (_key != StateKey_NotSet)
			_engine->getScriptManager()->setStateValue(_key, 1);

		// Change filename.raw into filename.sub
		Common::String subname = filename;
		subname.setChar('s', subname.size() - 3);
		subname.setChar('u', subname.size() - 2);
		subname.setChar('b', subname.size() - 1);

		if (_engine->getSearchManager()->hasFile(subname))
			_sub = new Subtitle(_engine, subname);

		_loaded = true;
	}
}
Ejemplo n.º 8
0
int AdlEngine_v2::o2_tellTime(ScriptEnv &e) {
	OP_DEBUG_0("\tTELL_TIME()");

	Common::String time = _strings_v2.time;

	time.setChar(APPLECHAR('0') + _state.time.hours / 10, 12);
	time.setChar(APPLECHAR('0') + _state.time.hours % 10, 13);
	time.setChar(APPLECHAR('0') + _state.time.minutes / 10, 15);
	time.setChar(APPLECHAR('0') + _state.time.minutes % 10, 16);

	printString(time);

	return 0;
}
Ejemplo n.º 9
0
bool Debugger::Cmd_DumpVocab(int argc, const char **argv) {
	Common::DumpFile outFile;
	outFile.open("vocab.txt");

	for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) {
		Common::String curId = Common::String::format("%x", i + 1);
		Common::String curVocab = _vm->_game->_scene.getVocab(i + 1);
		curVocab.toUppercase();

		for (uint j = 0; j < curVocab.size(); j++) {
			if (curVocab[j] == ' ' || curVocab[j] == '-')
				curVocab.setChar('_', j);
		}

		Common::String cur = "\tNOUN_" + curVocab + " = 0x" + curId + ",\n";

		outFile.writeString(cur.c_str());
	}

	outFile.flush();
	outFile.close();

	debugPrintf("Game vocab dumped\n");

	return true;
}
Ejemplo n.º 10
0
bool Debugger::Cmd_DumpItems(int argc, const char **argv) {
	InventoryObjects &objects = _vm->_game->_objects;

	Common::DumpFile outFile;
	outFile.open("items.txt");

	for (uint32 i = 0; i < objects.size(); i++) {
		Common::String curId = Common::String::format("%d", i);
		Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId);
		desc.toUppercase();

		for (uint j = 0; j < desc.size(); j++) {
			if (desc[j] == ' ' || desc[j] == '-')
				desc.setChar('_', j);
		}

		Common::String cur = "\tOBJ_" + desc + " = " + curId + ",\n";

		outFile.writeString(cur.c_str());
	}

	outFile.flush();
	outFile.close();

	debugPrintf("Game items dumped\n");

	return true;
}
Ejemplo n.º 11
0
void Inter_Geisha::oGeisha_checkData(OpFuncParams &params) {
	Common::String file = _vm->_game->_script->evalString();
	int16 varOff = _vm->_game->_script->readVarIndex();

	file.toLowercase();
	if (file.hasSuffix(".0ot"))
		file.setChar('t', file.size() - 3);

	bool exists = false;

	SaveLoad::SaveMode mode = _vm->_saveLoad->getSaveMode(file.c_str());
	if (mode == SaveLoad::kSaveModeNone) {

		exists = _vm->_dataIO->hasFile(file);
		if (!exists) {
			// NOTE: Geisha looks if fin.tot exists to check if it needs to open disk3.stk.
			//       This is completely normal, so don't print a warning.
			if (file != "fin.tot")
				warning("File \"%s\" not found", file.c_str());
		}

	} else if (mode == SaveLoad::kSaveModeSave)
		exists = _vm->_saveLoad->getSize(file.c_str()) >= 0;
	else if (mode == SaveLoad::kSaveModeExists)
		exists = true;

	WRITE_VAR_OFFSET(varOff, exists ? 50 : (uint32)-1);
}
Ejemplo n.º 12
0
void MADSAction::appendVocab(int vocabId, bool capitalize) {
	Common::String vocabStr = _vm->_game->_scene.getVocab(vocabId);
	if (capitalize)
		vocabStr.setChar(toupper(vocabStr[0]), 0);

	_statusText += vocabStr;
	_statusText += " ";
}
Ejemplo n.º 13
0
int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList) {
	if (_mouseFlag == 0 || _mouseFlag == 3) {
		return -1;
	}
	Common::Point mousePos = _system->getEventManager()->getMousePos();
	int mobNumber = getMob(mobList, usePriorityList, mousePos.x + _picWindowX, mousePos.y);

	if (mobNumber != -1) {
		Common::String mobName = mobList[mobNumber]._name;

		if (getLanguage() == Common::DE_DEU) {
			for (uint i = 0; i < mobName.size(); i++) {
				switch (mobName[i]) {
				case '\xc4':
					mobName.setChar('\x83', i);
					break;
				case '\xd6':
					mobName.setChar('\x84', i);
					break;
				case '\xdc':
					mobName.setChar('\x85', i);
					break;
				case '\xdf':
					mobName.setChar('\x7f', i);
					break;
				case '\xe4':
					mobName.setChar('\x80', i);
					break;
				case '\xf6':
					mobName.setChar('\x81', i);
					break;
				case '\xfc':
					mobName.setChar('\x82', i);
					break;
				}
			}
		}

		uint16 textW = getTextWidth(mobName.c_str());

		uint16 x = mousePos.x - textW / 2;
		if (x > screen->w) {
			x = 0;
		}

		if (x + textW > screen->w) {
			x = screen->w - textW;
		}

		uint16 y = mousePos.y - _font->getFontHeight();
		if (y > screen->h) {
			y = _font->getFontHeight() - 2;
		}

		_font->drawString(screen, mobName, x, y, screen->w, 216);
	}

	return mobNumber;
}
Ejemplo n.º 14
0
void HiRes1Engine::wordWrap(Common::String &str) const {
	uint end = 39;

	while (1) {
		if (str.size() <= end)
			return;

		while (str[end] != APPLECHAR(' '))
			--end;

		str.setChar(APPLECHAR('\r'), end);
		end += 40;
	}
}
Ejemplo n.º 15
0
Common::String DefinitionRegistry::stringToCamelCase(const Common::String &input) {
	Common::String clean = input;

	// First replace all non alphanumerical characters with spaces
	for (uint i = 0; i < clean.size(); i++) {
		if (!Common::isAlnum(clean[i])) {
			clean.setChar(' ', i);
		}
	}

	// Then turn the string into camel case
	Common::String output;
	Common::StringTokenizer tokens = Common::StringTokenizer(clean);
	while (!tokens.empty()) {
		Common::String token = tokens.nextToken();

		char upperFirstLetter = toupper(token[0]);
		token.setChar(upperFirstLetter, 0);

		output += token;
	}

	return output;
}
Ejemplo n.º 16
0
/**
 * Handles the sciAudio calls in fanmade games.
 * sciAudio is an external .NET library for playing MP3 files in fanmade games.
 * It runs in the background, and obtains sound commands from the
 * currently running game via text files (called "conductor files").
 * For further info, check: http://sciprogramming.com/community/index.php?topic=634.0
 */
void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan) {
	// TODO: This is a bare bones implementation. Only the play/playx and stop commands
	// are handled for now - the other commands haven't been observed in any fanmade game
	// yet. All the volume related and fading functionality is currently missing.

	Kernel *kernel = g_sci->getKernel();

	reg_t commandReg = readSelector(segMan, sciAudioObject, kernel->findSelector("command"));
	Common::String command = segMan->getString(commandReg);

	if (command == "play" || command == "playx") {
#ifdef USE_MAD
		reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName"));
		Common::String fileName = segMan->getString(fileNameReg);

		int16 loopCount = (int16)readSelectorValue(segMan, sciAudioObject, kernel->findSelector("loopCount"));
		// When loopCount is -1, we treat it as infinite looping, else no looping is done.
		// This is observed by game scripts, which can set loopCount to all sorts of random values.
		// Adjust loopCount for ScummVM's LoopingAudioStream semantics
		loopCount = (loopCount == -1) ? 0 : 1;

		// Determine sound type
		Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType;
		if (fileName.hasPrefix("music"))
			soundType = Audio::Mixer::kMusicSoundType;
		else if (fileName.hasPrefix("speech"))
			soundType = Audio::Mixer::kSpeechSoundType;

		Common::File *sciAudio = new Common::File();
		// Replace backwards slashes
		for (uint i = 0; i < fileName.size(); i++) {
			if (fileName[i] == '\\')
				fileName.setChar('/', i);
		}
		sciAudio->open("sciAudio/" + fileName);

		Audio::SeekableAudioStream *audioStream = Audio::makeMP3Stream(sciAudio, DisposeAfterUse::YES);

		// We only support one audio handle
		_mixer->playStream(soundType, &_audioHandle,
							Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount));
#endif
	} else if (command == "stop") {
		_mixer->stopHandle(_audioHandle);
	} else {
		warning("Unhandled sciAudio command: %s", command.c_str());
	}
}
Ejemplo n.º 17
0
Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &filename) {
	Common::String upcName = filename;
	upcName.toUppercase();
	Common::SeekableReadStream *file = nullptr;

	// correct slashes
	for (uint32 i = 0; i < upcName.size(); i++) {
		if (upcName[(int32)i] == '/') {
			upcName.setChar('\\', (uint32)i);
		}
	}
	Common::ArchiveMemberPtr entry = _packages.getMember(upcName);
	if (!entry) {
		return nullptr;
	}
	file = entry->createReadStream();
	return file;
}
Ejemplo n.º 18
0
Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &filename) {
	Common::String upcName = filename;
	upcName.toUppercase();
	Common::SeekableReadStream *file = NULL;
	char fileName[MAX_PATH_LENGTH];
	strcpy(fileName, upcName.c_str());

	// correct slashes
	for (uint32 i = 0; i < upcName.size(); i++) {
		if (upcName[(int32)i] == '/') {
			upcName.setChar('\\', (uint32)i);
		}
	}
	Common::ArchiveMemberPtr entry = _packages.getMember(upcName);
	if (!entry) {
		return NULL;
	}
	file = entry->createReadStream();
	return file;
}
Ejemplo n.º 19
0
DECFile::DECFile(GobEngine *vm, const Common::String &fileName,
                 uint16 width, uint16 height, uint8 bpp) : _vm(vm),
	_width(width), _height(height), _bpp(bpp), _hasPadding(false), _backdrop(0) {

	bool bigEndian = false;
	Common::String endianFileName = fileName;

	if ((_vm->getEndiannessMethod() == kEndiannessMethodAltFile) &&
	    !_vm->_dataIO->hasFile(fileName)) {
		// If the game has alternate big-endian files, look if one exist

		Common::String alternateFileName = fileName;
		alternateFileName.setChar('_', 0);

		if (_vm->_dataIO->hasFile(alternateFileName)) {
			bigEndian      = true;
			endianFileName = alternateFileName;
		}
	} else if ((_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
	           ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
	            (_vm->getEndianness() == kEndiannessBE)))
		// Game always little endian or it follows the system and it is big endian
		bigEndian = true;

	Common::SeekableReadStream *ani = _vm->_dataIO->getFile(endianFileName);
	if (ani) {
		Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), bigEndian, DisposeAfterUse::YES);

		// The big endian version pads a few fields to even size
		_hasPadding = bigEndian;

		load(sub, fileName);
		return;
	}

	warning("DECFile::DECFile(): No such file \"%s\" (\"%s\")", endianFileName.c_str(), fileName.c_str());
}
Ejemplo n.º 20
0
void Inter_Geisha::oGeisha_checkData(OpFuncParams &params) {
	Common::String file = _vm->_game->_script->evalString();
	int16 varOff = _vm->_game->_script->readVarIndex();

	file.toLowercase();
	if (file.hasSuffix(".0ot"))
		file.setChar('t', file.size() - 3);

	bool exists = false;

	SaveLoad::SaveMode mode = _vm->_saveLoad->getSaveMode(file.c_str());
	if (mode == SaveLoad::kSaveModeNone) {

		exists = _vm->_dataIO->hasFile(file);
		if (!exists)
			warning("File \"%s\" not found", file.c_str());

	} else if (mode == SaveLoad::kSaveModeSave)
		exists = _vm->_saveLoad->getSize(file.c_str()) >= 0;
	else if (mode == SaveLoad::kSaveModeExists)
		exists = true;

	WRITE_VAR_OFFSET(varOff, exists ? 50 : (uint32)-1);
}
Ejemplo n.º 21
0
void SceneTeleporter::teleporterHandleKey() {
	switch (_game._trigger) {
	case 0: {
		_game._player._stepEnabled = false;
		Common::Point msgPos = teleporterComputeLocation();
		_handSequenceId = _scene->_sequences.startPingPongCycle(_handSpriteId, false, 4, 2, 0, 0);
		_scene->_sequences.setPosition(_handSequenceId, msgPos);
		_scene->_sequences.setDepth(_handSequenceId, 2);
		_scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_LOOP, 0, 1);
		_scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2);

		if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL)
			_vm->_events->hideCursor();

		}
		break;

	case 1:
		_scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_SPRITE, 3, 3);
		if (_buttonTyped <= 9) {
			if (_digitCount < 4) {
				_curCode *= 10;
				_curCode += _buttonTyped;
				_digitCount++;

				Common::String format = "%01d";
				format.setChar('0' + _digitCount, 2);
				_msgText = Common::String::format(format.c_str(), _curCode);
				if (_digitCount < 4)
					_msgText += "_";

				if (_scene->_currentSceneId != 711)
					_vm->_sound->command(32);
			}
		} else if (_buttonTyped == 11) {
			_digitCount = 0;
			_curCode = 0;
			_msgText = "_";
			if (_scene->_currentSceneId != 711)
				_vm->_sound->command(33);
		} else if (_digitCount == 4) {
			if (_scene->_currentSceneId != 711)
				_finishedCodeCounter = 1;

			if (teleporterAddress(_curCode, true) > 0) {
				_vm->_palette->setEntry(252, 0, 63, 0);
				if (_scene->_currentSceneId != 711)
					_vm->_sound->command(34);
			} else {
				_vm->_palette->setEntry(252, 63, 0, 0);
				if (_scene->_currentSceneId != 711)
					_vm->_sound->command(35);
			}
		}

		if (_scene->_currentSceneId != 711) {
			if (_curMessageId >= 0)
				_scene->_kernelMessages.remove(_curMessageId);
			_curMessageId = _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, INDEFINITE_TIMEOUT, _msgText);
		}
		break;

	case 2:
		if (_finishedCodeCounter == 1) {
			_finishedCodeCounter++;

			if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL)
				_scene->_nextSceneId = 202;
			else {
				_vm->_events->showCursor();
				int destination = teleporterAddress(_curCode, true);

				if (destination > 0) {
					_globals[kTeleporterCommand] = 2;
					_scene->_nextSceneId = _teleporterSceneId;
					_globals[kTeleporterDestination] = destination;
				} else {
					_globals[kTeleporterCommand] = 4;
					_scene->_nextSceneId = _teleporterSceneId;
				}
			}
		} else if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL)
			_scene->_sequences.addTimer(30, 230 + _meteorologistCurPlace);

		break;

	case 3:
		if (!_finishedCodeCounter) {
			if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) {
				_game._player._stepEnabled = true;
				_vm->_events->showCursor();
			}
		}
		break;

	default:
		break;
	}
}
Ejemplo n.º 22
0
Common::String HiRes4Engine_Atari::formatVerbError(const Common::String &verb) const {
	Common::String err = _strings.verbError;
	for (uint i = 0; i < verb.size(); ++i)
		err.setChar(verb[i], i + 8);
	return err;
}
Ejemplo n.º 23
0
void Room::feather1ReachedVineToClimbDown() {
	const char *crew = "ksmr";
	Common::String anim = "s5r1_d";
	anim.setChar(crew[_roomVar.feather.crewmanClimbingVine], 4);
	loadActorAnimC(_roomVar.feather.crewmanClimbingVine, anim, VINE_BOT_X, VINE_BOT_Y, &Room::feather1ClimbedDownVine);
}
Ejemplo n.º 24
0
reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
	reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text));

	// The object in the text selector of the item can be either a raw string
	// or a Str object. In the latter case, we need to access the object's data
	// selector to get the raw string.
	if (_segMan->isHeapObject(stringObject))
		stringObject = readSelector(_segMan, stringObject, SELECTOR(data));

	Common::String text = _segMan->getString(stringObject);
	// HACK: The character offsets of the up and down arrow buttons are off by one
	// in GK1, for some unknown reason. Fix them here.
	if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) {
		text.setChar(text[0] + 1, 0);
	}
	GuiResourceId fontId = readSelectorValue(_segMan, textObject, SELECTOR(font));
	GfxFont *font = _cache->getFont(fontId);
	bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed));
	int16 alignment = readSelectorValue(_segMan, textObject, SELECTOR(mode));
	uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore));
	uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back));

	Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject);
	uint16 width = nsRect.width() + 1;
	uint16 height = nsRect.height() + 1;

	// Limit rectangle dimensions, if requested
	if (maxWidth > 0)
		width = maxWidth;
	if (maxHeight > 0)
		height = maxHeight;

	// Upscale the coordinates/width if the fonts are already upscaled
	if (_screen->fontIsUpscaled()) {
		width = width * _screen->getDisplayWidth() / _screen->getWidth();
		height = height * _screen->getDisplayHeight() / _screen->getHeight();
	}

	int entrySize = width * height + BITMAP_HEADER_SIZE;
	reg_t memoryId = NULL_REG;
	if (prevHunk.isNull()) {
		memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize);
		writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId);
	} else {
		memoryId = prevHunk;
	}
	byte *memoryPtr = _segMan->getHunkPointer(memoryId);

	if (prevHunk.isNull())
		memset(memoryPtr, 0, BITMAP_HEADER_SIZE);

	byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
	memset(bitmap, backColor, width * height);

	// Save totalWidth, totalHeight
	WRITE_LE_UINT16(memoryPtr, width);
	WRITE_LE_UINT16(memoryPtr + 2, height);

	int16 charCount = 0;
	uint16 curX = 0, curY = 0;
	const char *txt = text.c_str();
	int16 textWidth, textHeight, totalHeight = 0, offsetX = 0, offsetY = 0;
	uint16 start = 0;

	// Calculate total text height
	while (*txt) {
		charCount = GetLongest(txt, width, font);
		if (charCount == 0)
			break;

		Width(txt, 0, (int16)strlen(txt), fontId, textWidth, textHeight, true);

		totalHeight += textHeight;
		txt += charCount;
		while (*txt == ' ')
			txt++; // skip over breaking spaces
	}

	txt = text.c_str();

	// Draw text in buffer
	while (*txt) {
		charCount = GetLongest(txt, width, font);
		if (charCount == 0)
			break;
		Width(txt, start, charCount, fontId, textWidth, textHeight, true);

		switch (alignment) {
		case SCI_TEXT32_ALIGNMENT_RIGHT:
			offsetX = width - textWidth;
			break;
		case SCI_TEXT32_ALIGNMENT_CENTER:
			// Center text both horizontally and vertically
			offsetX = (width - textWidth) / 2;
			offsetY = (height - totalHeight) / 2;
			break;
		case SCI_TEXT32_ALIGNMENT_LEFT:
			offsetX = 0;
			break;

		default:
			warning("Invalid alignment %d used in TextBox()", alignment);
		}

		for (int i = 0; i < charCount; i++) {
			unsigned char curChar = txt[i];
			font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height);
			curX += font->getCharWidth(curChar);
		}

		curX = 0;
		curY += font->getHeight();
		txt += charCount;
		while (*txt == ' ')
			txt++; // skip over breaking spaces
	}

	return memoryId;
}
Ejemplo n.º 25
0
/**
 * Handles the sciAudio calls in fanmade games.
 * sciAudio is an external .NET library for playing MP3 files in fanmade games.
 * It runs in the background, and obtains sound commands from the
 * currently running game via text files (called "conductor files").
 * For further info, check: http://sciprogramming.com/community/index.php?topic=634.0
 */
void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan) {
	// TODO: This is a bare bones implementation. Only the play/playx and stop commands
	// are handled for now - the other commands haven't been observed in any fanmade game
	// yet. All the volume related and fading functionality is currently missing.

	Kernel *kernel = g_sci->getKernel();

	reg_t commandReg = readSelector(segMan, sciAudioObject, kernel->findSelector("command"));
	Common::String command = segMan->getString(commandReg);

	if (command == "play" || command == "playx") {
		reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName"));
		Common::String fileName = segMan->getString(fileNameReg);

		reg_t loopCountReg = readSelector(segMan, sciAudioObject, kernel->findSelector("loopCount"));
		Common::String loopCountStr = segMan->getString(loopCountReg);
		int16 loopCount = atoi(loopCountStr.c_str());

		// Adjust loopCount for ScummVM's LoopingAudioStream semantics
		if (loopCount == -1) {
			loopCount = 0; // loop endlessly
		} else if (loopCount >= 0) {
			// sciAudio loopCount == 0 -> play 1 time  -> ScummVM's loopCount should be 1
			// sciAudio loopCount == 1 -> play 2 times -> ScummVM's loopCount should be 2
			loopCount++;
		} else {
			loopCount = 1; // play once in case the value makes no sense
		}

		// Determine sound type
		Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType;
		if (fileName.hasPrefix("music"))
			soundType = Audio::Mixer::kMusicSoundType;
		else if (fileName.hasPrefix("speech"))
			soundType = Audio::Mixer::kSpeechSoundType;

		// Determine compression
		uint32 audioCompressionType = 0;
		if ((fileName.hasSuffix(".mp3")) || (fileName.hasSuffix(".sciAudio")) || (fileName.hasSuffix(".sciaudio"))) {
			audioCompressionType = MKTAG('M','P','3',' ');
		} else if (fileName.hasSuffix(".wav")) {
			audioCompressionType = MKTAG('W','A','V',' ');
		} else if (fileName.hasSuffix(".aiff")) {
			audioCompressionType = MKTAG('A','I','F','F');
		} else {
			error("sciAudio: unsupported file type");
		}

		Common::File *sciAudioFile = new Common::File();
		// Replace backwards slashes
		for (uint i = 0; i < fileName.size(); i++) {
			if (fileName[i] == '\\')
				fileName.setChar('/', i);
		}
		sciAudioFile->open("sciAudio/" + fileName);

		Audio::RewindableAudioStream *audioStream = nullptr;

		switch (audioCompressionType) {
		case MKTAG('M','P','3',' '):
#ifdef USE_MAD
			audioStream = Audio::makeMP3Stream(sciAudioFile, DisposeAfterUse::YES);
#endif
			break;
		case MKTAG('W','A','V',' '):
			audioStream = Audio::makeWAVStream(sciAudioFile, DisposeAfterUse::YES);
			break;
		case MKTAG('A','I','F','F'):
			audioStream = Audio::makeAIFFStream(sciAudioFile, DisposeAfterUse::YES);
			break;
		default:
			break;
		}

		if (!audioStream) {
			error("sciAudio: requested compression not compiled into ScummVM");
		}

		// We only support one audio handle
		_mixer->playStream(soundType, &_audioHandle,
							Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount));
	} else if (command == "stop") {
		_mixer->stopHandle(_audioHandle);
	} else {
		warning("Unhandled sciAudio command: %s", command.c_str());
	}
}
Ejemplo n.º 26
0
void UserInterface::writeVocab(ScrCategory category, int id) {
	Common::Rect bounds;
	if (!getBounds(category, id, bounds))
		return;

	Scene &scene = _vm->_game->_scene;
	Font *font = nullptr;

	int vocabId;
	Common::String vocabStr;
	switch (category) {
	case CAT_COMMAND:
		font = _vm->_font->getFont(FONT_INTERFACE);
		vocabId = scene._verbList[id]._id;
		if (id == _highlightedCommandIndex) {
			_vm->_font->setColorMode(SELMODE_HIGHLIGHTED);
		} else {
			_vm->_font->setColorMode(id == _selectedActionIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED);
		}
		vocabStr = scene.getVocab(vocabId);
		vocabStr.setChar(toupper(vocabStr[0]), 0);
		font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
		break;

	case CAT_INV_LIST:
		font = _vm->_font->getFont(FONT_INTERFACE);
		vocabId = _vm->_game->_objects.getItem(id)._descId;
		if (id == _highlightedInvIndex) {
			_vm->_font->setColorMode(SELMODE_HIGHLIGHTED);
		} else {
			_vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED);
		}

		vocabStr = scene.getVocab(vocabId);
		vocabStr.setChar(toupper(vocabStr[0]), 0);
		font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
		break;

	case CAT_TALK_ENTRY:
		font = _vm->_font->getFont(FONT_INTERFACE);
		font->setColorMode(id == _highlightedCommandIndex ? SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED);
		font->writeString(this, _talkStrings[id], Common::Point(bounds.left, bounds.top));
		break;

	case CAT_INV_SCROLLER:
		font = _vm->_font->getFont(FONT_MISC);

		switch (id) {
		case 1:
			vocabStr = "a";
			break;
		case 2:
			vocabStr = "b";
			break;
		case 3:
			vocabStr = "d";
			break;
		case 4:
			vocabStr = "c";
			break;
		default:
			break;
		}

		font->setColorMode((id == 4) || (_scrollbarActive == SCROLLBAR_ELEVATOR) ?
			SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED);
		font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
		break;
	default:
		// Item specific verbs
		font = _vm->_font->getFont(FONT_INTERFACE);
		vocabId = _vm->_game->_objects.getItem(_selectedInvIndex)._vocabList[id]._vocabId;
		if (id == _highlightedItemVocabIndex) {
			_vm->_font->setColorMode(SELMODE_HIGHLIGHTED);
		} else {
			_vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED);
			vocabStr = scene.getVocab(vocabId);
			vocabStr.setChar(toupper(vocabStr[0]), 0);
			font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top));
			break;
		}
		break;
	}
}
Ejemplo n.º 27
0
bool WidgetFiles::getFilename() {
	Events &events = *_vm->_events;
	TattooScene &scene = *(TattooScene *)_vm->_scene;
	Screen &screen = *_vm->_screen;
	Talk &talk = *_vm->_talk;
	int index = 0;
	int done = 0;
	bool blinkFlag = false;
	int blinkCountdown = 0;
	int cursorColor = 192;
	byte color, textColor;
	bool insert = true;

	assert(_selector != -1);
	Common::Point pt(_surface.stringWidth("00.") + _surface.widestChar() + 5,
		_surface.fontHeight() + 14 + (_selector - _savegameIndex) * (_surface.fontHeight() + 1));

	Common::String numStr = Common::String::format("%d.", _selector + 1);
	_surface.writeString(numStr, Common::Point(_surface.widestChar(), pt.y), COMMAND_HIGHLIGHTED);

	Common::String filename = _savegames[_selector];

	if (isSlotEmpty(_selector)) {
		index = 0;
		_surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.right - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
		filename = "";
	} else {
		index = filename.size();
		_surface.writeString(filename, pt, COMMAND_HIGHLIGHTED);
		pt.x = _surface.stringWidth("00.") + _surface.stringWidth(filename) + _surface.widestChar() + 5;
	}

	do {
		scene.doBgAnim();

		if (talk._talkToAbort)
			return false;

		char currentChar = (index == (int)filename.size()) ? ' ' : filename[index];
		Common::String charString = Common::String::format("%c", currentChar);
		int width = screen.charWidth(currentChar);

		// Wait for keypress
		while (!events.kbHit()) {
			events.pollEventsAndWait();
			events.setButtonState();

			scene.doBgAnim();

			if (talk._talkToAbort)
				return false;

			if (--blinkCountdown <= 0) {
				blinkCountdown = 3;
				blinkFlag = !blinkFlag;
				if (blinkFlag) {
					textColor = 236;
					color = cursorColor;
				} else {
					textColor = COMMAND_HIGHLIGHTED;
					color = TRANSPARENCY;
				}

				_surface.fillRect(Common::Rect(pt.x, pt.y, pt.x + width, pt.y + _surface.fontHeight()), color);
				if (currentChar != ' ')
					_surface.writeString(charString, pt, textColor);
			}
			if (_vm->shouldQuit())
				return false;
		}

		Common::KeyState keyState = events.getKey();
		if (keyState.keycode == Common::KEYCODE_BACKSPACE && index > 0) {
			pt.x -= _surface.charWidth(filename[index - 1]);
			--index;

			if (insert) {
				filename.deleteChar(index);
			} else {
				filename.setChar(' ', index);
			}

			_surface.fillRect(Common::Rect(pt.x, pt.y, _surface.width() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
			_surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);

		} else if ((keyState.keycode == Common::KEYCODE_LEFT && index > 0)
				|| (keyState.keycode == Common::KEYCODE_RIGHT && index < 49 && pt.x < (_bounds.right - BUTTON_SIZE - 20))
				|| (keyState.keycode == Common::KEYCODE_HOME && index > 0)
				|| (keyState.keycode == Common::KEYCODE_END)) {
			_surface.fillRect(Common::Rect(pt.x, pt.y, pt.x + width, pt.y + _surface.fontHeight()), TRANSPARENCY);
			if (currentChar)
				_surface.writeString(charString, pt, COMMAND_HIGHLIGHTED);

			switch (keyState.keycode) {
			case Common::KEYCODE_LEFT:
				pt.x -= _surface.charWidth(filename[index - 1]);
				--index;
				break;

			case Common::KEYCODE_RIGHT:
				pt.x += _surface.charWidth(filename[index]);
				++index;
				break;

			case Common::KEYCODE_HOME:
				pt.x = _surface.stringWidth("00.") + _surface.widestChar() + 5;
				index = 0;
				break;

			case Common::KEYCODE_END:
				pt.x = _surface.stringWidth("00.") + _surface.stringWidth(filename) + _surface.widestChar() + 5;
				index = filename.size();

				while (filename[index - 1] == ' ' && index > 0) {
					pt.x -= _surface.charWidth(filename[index - 1]);
					--index;
				}
				break;

			default:
				break;
			}
		} else if (keyState.keycode == Common::KEYCODE_INSERT) {
			insert = !insert;
			if (insert)
				cursorColor = 192;
			else
				cursorColor = 200;

		} else if (keyState.keycode == Common::KEYCODE_DELETE) {
			filename.deleteChar(index);

			_surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.right - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
			_surface.writeString(filename + index, pt, COMMAND_HIGHLIGHTED);

		} else  if (keyState.keycode == Common::KEYCODE_RETURN) {
			done = 1;

		} else if (keyState.keycode == Common::KEYCODE_ESCAPE) {
			_selector = -1;
			render(RENDER_NAMES_AND_SCROLLBAR);
			done = -1;
		}

		if ((keyState.ascii >= ' ') && (keyState.ascii <= 'z') && (index < 50)) {
			if (pt.x + _surface.charWidth(keyState.ascii) < _surface.w - BUTTON_SIZE - 20) {
				if (insert)
					filename.insertChar(keyState.ascii, index);
				else
					filename.setChar(keyState.ascii, index);

				_surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.width() - BUTTON_SIZE - 9,
					pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
				_surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
				pt.x += _surface.charWidth(keyState.ascii);
				++index;
			}
		}
	} while (!done && !_vm->shouldQuit());

	scene.doBgAnim();

	if (talk._talkToAbort)
		return false;

	if (done == 1)
		_savegames[_selector] = filename;

	return done == 1;
}
Ejemplo n.º 28
0
void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t contentVmPtr) {
	GuiMenuEntry *menuEntry;
	uint16 itemCount = 0;
	GuiMenuItemEntry *itemEntry;
	int contentSize = content.size();
	int separatorCount;
	int curPos, beginPos, endPos, tempPos;
	int tagPos, rightAlignedPos, functionPos, altPos, controlPos;
	const char *tempPtr;

	// Sierra SCI starts with id 1, so we do so as well
	menuEntry = new GuiMenuEntry(_list.size() + 1);
	menuEntry->text = title;
	_list.push_back(menuEntry);

	curPos = 0;
	uint16 listSize = _list.size();

	do {
		itemCount++;
		itemEntry = new GuiMenuItemEntry(listSize, itemCount);

		beginPos = curPos;

		// Now go through the content till we find end-marker and collect data about it.
		// ':' is an end-marker for each item.
		tagPos = 0; rightAlignedPos = 0;
		controlPos = 0; altPos = 0; functionPos = 0;
		while ((curPos < contentSize) && (content[curPos] != ':')) {
			switch (content[curPos]) {
			case '=': // Set tag
				// Special case for normal animation speed - they use right
				// aligned "=" for that one, so we ignore it as being recognized
				// as tag marker.
				if (rightAlignedPos == curPos - 1)
					break;
				if (tagPos)
					error("multiple tag markers within one menu-item");
				tagPos = curPos;
				break;
			case '`': // Right-aligned
				if (rightAlignedPos)
					error("multiple right-aligned markers within one menu-item");
				rightAlignedPos = curPos;
				break;
			case '^': // Ctrl-prefix
				if (controlPos)
					error("multiple control markers within one menu-item");
				controlPos = curPos;
				break;
			case '@': // Alt-prefix
				if (altPos)
					error("multiple alt markers within one menu-item");
				altPos = curPos;
				break;
			case '#': // Function-prefix
				if (functionPos)
					error("multiple function markers within one menu-item");
				functionPos = curPos;
				break;
			}
			curPos++;
		}
		endPos = curPos;

		// Control/Alt/Function key mapping...
		if (controlPos) {
			content.setChar(SCI_MENU_REPLACE_ONCONTROL, controlPos);
			itemEntry->keyModifier = SCI_KEYMOD_CTRL;
			tempPos = controlPos + 1;
			if (tempPos >= contentSize)
				error("control marker at end of item");
			itemEntry->keyPress = tolower(content[tempPos]);
			content.setChar(toupper(content[tempPos]), tempPos);
		}
		if (altPos) {
			content.setChar(SCI_MENU_REPLACE_ONALT, altPos);
			itemEntry->keyModifier = SCI_KEYMOD_ALT;
			tempPos = altPos + 1;
			if (tempPos >= contentSize)
				error("alt marker at end of item");
			itemEntry->keyPress = tolower(content[tempPos]);
			content.setChar(toupper(content[tempPos]), tempPos);
		}
		if (functionPos) {
			content.setChar(SCI_MENU_REPLACE_ONFUNCTION, functionPos);
			tempPos = functionPos + 1;
			if (tempPos >= contentSize)
				error("function marker at end of item");
			itemEntry->keyPress = content[tempPos];
			switch (content[functionPos + 1]) {
			case '1': itemEntry->keyPress = SCI_KEY_F1; break;
			case '2': itemEntry->keyPress = SCI_KEY_F2; break;
			case '3': itemEntry->keyPress = SCI_KEY_F3; break;
			case '4': itemEntry->keyPress = SCI_KEY_F4; break;
			case '5': itemEntry->keyPress = SCI_KEY_F5; break;
			case '6': itemEntry->keyPress = SCI_KEY_F6; break;
			case '7': itemEntry->keyPress = SCI_KEY_F7; break;
			case '8': itemEntry->keyPress = SCI_KEY_F8; break;
			case '9': itemEntry->keyPress = SCI_KEY_F9; break;
			case '0': itemEntry->keyPress = SCI_KEY_F10; break;
			default:
				error("illegal function key specified");
			}
		}

		// Now get all strings
		tempPos = endPos;
		if (rightAlignedPos) {
			tempPos = rightAlignedPos;
		} else if (tagPos) {
			tempPos = tagPos;
		}
		curPos = beginPos;
		separatorCount = 0;
		while (curPos < tempPos) {
			switch (content[curPos]) {
			case '!':
			case '-':
			case ' ':
				separatorCount++;
				break;
			case '%':
				// Some multilingual sci01 games use e.g. '--!%G--!' (which doesn't really make sense)
				separatorCount += 2;
				curPos++;
			}
			curPos++;
		}
		if (separatorCount == tempPos - beginPos) {
			itemEntry->separatorLine = true;
		} else {
			// We don't strSplit here, because multilingual SCI01 support
			// language switching on the fly, so we have to do this everytime
			// the menu is called.
			itemEntry->text = Common::String(content.c_str() + beginPos, tempPos - beginPos);

			// LSL6 uses "Ctrl-" prefix string instead of ^ like all the other games do
			tempPtr = itemEntry->text.c_str();
			tempPtr = strstr(tempPtr, "Ctrl-");
			if (tempPtr) {
				itemEntry->keyModifier = SCI_KEYMOD_CTRL;
				itemEntry->keyPress = tolower(tempPtr[5]);
			}
		}
		itemEntry->textVmPtr = contentVmPtr;
		itemEntry->textVmPtr.incOffset(beginPos);

		if (rightAlignedPos) {
			rightAlignedPos++;
			tempPos = endPos;
			// some games have tagPos in front of right rightAlignedPos
			// some have it the other way... (qfg1ega)
			if (tagPos && tagPos >= rightAlignedPos)
				tempPos = tagPos;
			itemEntry->textRightAligned = Common::String(content.c_str() + rightAlignedPos, tempPos - rightAlignedPos);
			// Remove ending space, if there is one. Strangely sometimes there
			// are lone spaces at the end in some games
			if (itemEntry->textRightAligned.hasSuffix(" "))
				itemEntry->textRightAligned.deleteLastChar();
			// - and + are used sometimes for volume control/animation speed,
			// = sometimes for animation speed
			if (itemEntry->textRightAligned == "-") {
				itemEntry->keyPress = '-';
			} else if (itemEntry->textRightAligned == "+") {
				itemEntry->keyPress = '+';
			} else if (itemEntry->textRightAligned == "=") {
				itemEntry->keyPress = '=';
			}
		}

		if (tagPos) {
			tempPos = functionPos + 1;
			if (tempPos >= contentSize)
				error("tag marker at end of item");
			itemEntry->tag = atoi(content.c_str() + tempPos);
		}

		curPos = endPos + 1;

		_itemList.push_back(itemEntry);
	} while (curPos < contentSize);
}
Ejemplo n.º 29
0
MsCabinet::MsCabinet(Common::SeekableReadStream* data) :
	_data(data), _decompressor(0) {
	if (!_data)
		return;

	//CFHEADER PARSING

	// Verify Head-signature
	uint32 tag = _data->readUint32BE();
	if (tag != MKTAG('M','S','C','F'))
		return;

	/* uint32 reserved1 = */ _data->readUint32LE();
	uint32 length = _data->readUint32LE();
	if (length > uint32(_data->size()))
		return;

	/* uint32 reserved2 = */ _data->readUint32LE();
	uint32 filesOffset = _data->readUint32LE();
	/* uint32 reserved3 = */ _data->readUint32LE();

	byte versionMinor = _data->readByte();
	byte versionMajor = _data->readByte();
	if (versionMajor != 1 || versionMinor != 3)
		return;

	uint16 numFolders = _data->readUint16LE();
	uint16 numFiles = _data->readUint16LE();
	if (numFolders == 0 || numFiles == 0)
		return;

	//This implementation doesn't support multicabinet and reserved fields
	uint16 flags = _data->readUint16LE();
	if (flags != 0)
		return;

	/* uint16 setId = */ _data->readUint16LE();
	/* uint16 iCab = */ _data->readUint16LE();

	if (_data->err())
		return;

	//CFFOLDERs PARSING
	for (uint16 i = 0; i < numFolders; ++i) {
		FolderEntry fEntry;

		fEntry.offset = _data->readUint32LE();
		fEntry.num_blocks = _data->readUint16LE();
		fEntry.comp_type = _data->readUint16LE();

		if (_data->err())
			return;

		_folderMap[i] = fEntry;
	}

	//CFFILEs PARSING
	_data->seek(filesOffset);
	if (_data->err())
		return;

	for (uint16 i = 0; i < numFiles; ++i) {
		FileEntry fEntry;

		fEntry.length = _data->readUint32LE();
		fEntry.folderOffset = _data->readUint32LE();
		uint16 iFolder = _data->readUint16LE();
		/* uint16 date = */ _data->readUint16LE();
		/* uint16 time = */ _data->readUint16LE();
		/* uint16 attribs = */ _data->readUint16LE();
		Common::String name = readString(_data);
		for (uint l = 0; l < name.size(); ++l)
			if (name[l] == '\\')
				name.setChar('/', l);

		if (_data->err()) {
			_fileMap.clear();
			return;
		}

		if (_folderMap.contains(iFolder))
			fEntry.folder = &_folderMap[iFolder];
		else {
			_fileMap.clear();
			return;
		}

		_fileMap[name] = fEntry;
	}
}
Ejemplo n.º 30
0
void Room::feather1ReachedVineToClimbUp() {
	const char *crew = "ksmr";
	Common::String anim = "s5r1_c";
	anim.setChar(crew[_roomVar.feather.crewmanClimbingVine], 4);
	loadActorAnimC(_roomVar.feather.crewmanClimbingVine, anim, -1, -1, &Room::feather1ClimbedUpVine);
}