Пример #1
0
bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String &themeName) {
	// Check that header is not corrupted
	if ((byte)header[0] > 127) {
		warning("Corrupted theme header found");
		return false;
	}

	header.trim();

	if (header.empty())
		return false;

	if (header[0] != '[' || header.lastChar() != ']')
		return false;

	header.deleteChar(0);
	header.deleteLastChar();

	Common::StringTokenizer tok(header, ":");

	if (tok.nextToken() != SCUMMVM_THEME_VERSION_STR)
		return false;

	themeName = tok.nextToken();
	Common::String author = tok.nextToken();

	return tok.empty();
}
Пример #2
0
bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String &themeName) {
	header.trim();

	if (header.empty())
		return false;

	if (header[0] != '[' || header.lastChar() != ']')
		return false;

	header.deleteChar(0);
	header.deleteLastChar();

	Common::StringTokenizer tok(header, ":");

	if (tok.nextToken() != RESIDUAL_THEME_VERSION_STR)
		return false;

	themeName = tok.nextToken();
	Common::String author = tok.nextToken();

	return tok.empty();
}
Пример #3
0
void GameConversations::generateMessage(Common::Array<int> &messageList, Common::Array<int> &voiceList) {
	_dialogAltFlag = false;
	if (messageList.size() == 0)
		return;

	if (_dialog)
		delete _dialog;

	// Get the speaker portrait
	SpriteAsset &sprites = *_vm->_game->_scene._sprites[_speakerSeries[_personSpeaking]];
	MSprite *portrait = sprites.getFrame(_speakerFrame[_personSpeaking]);

	// Create the new text dialog
	_dialog = new TextDialog(_vm, FONT_INTERFACE,
		Common::Point(_popupX[_personSpeaking], _popupY[_personSpeaking]), 
		portrait, _popupMaxLen[_personSpeaking]);

	// Add in the lines
	for (uint msgNum = 0; msgNum < messageList.size(); ++msgNum) {
		ConvMessage &msg = _runningConv->_data._messages[messageList[msgNum]];
		uint stringIndex = msg._stringIndex;

		for (uint strNum = 0; strNum < msg._count; ++strNum, ++stringIndex) {
			Common::String textLine = _runningConv->_data._textLines[stringIndex];
			textLine.trim();
			_dialog->addLine(textLine);
		}
	}

	// Show the dialog
	_popupVisible = true;
	_dialog->show();

	// Play the speech if one was provided
	if (voiceList.size() > 0) {
		_vm->_audio->setSoundGroup(_runningConv->_data._speechFile);
		_vm->_audio->playSound(voiceList[0] - 1);
	}
}
Пример #4
0
void Conf::get(const Common::String &key, Common::String &field, const char *defaultVal) {
	field = ConfMan.hasKey(key) ? ConfMan.get(key) : defaultVal;
	field.trim();
}
Пример #5
0
Common::Error GagEngine::StateScript()
{
	Common::Error status(Common::kNoError);

	Common::File file;
	if(file.open(_script, *_archive))
	{
		// simple script parsing: skim through, find section and execute commands
		ParserState parse_state(PS_SECTION_SEARCH);
		Common::String buffer;
		Common::String command_name;

		bool done(false);
		while(!file.eos())
		{
			// add space for multiline command support
			Common::String line = file.readLine() + ' ';
			if(file.err())
			{
				status = Common::Error(Common::kReadingFailed, _script + ", readLine()");
				break;
			}

			bool skip_line(false);
			for(Common::String::const_iterator it = line.begin(); it != line.end(); ++it)
			{
				switch(parse_state)
				{
				case PS_SECTION_SEARCH:
					// section
					if(*it == '[')
					{
						buffer.clear();

						parse_state = PS_SECTION_NAME;
					}
					break;

				case PS_SECTION_NAME:
					// section end
					if(*it == ']')
					{
#ifdef DEBUG_SKIM_SCRIPT
						parse_state = PS_SECTION_BODY;
#else
						if(buffer == _section)
							parse_state = PS_SECTION_BODY;
						else if(buffer == _END_SECTION)
						{
							status = Common::Error(Common::kUnknownError, "[" + _section + "] script section not found");
							skip_line = true;
							done = true;
						}
						else
							parse_state = PS_SECTION_SEARCH;
#endif
					}
					else
						buffer += *it;
					break;

				case PS_SECTION_BODY:
					// section
					if(*it == '[')
					{
#ifdef DEBUG_SKIM_SCRIPT
						buffer.clear();
						parse_state = PS_SECTION_NAME;
#else
						skip_line = true;
						done = true;
#endif
					}
					// comment
					else if(*it == '*')
					{
						skip_line = true;
					}
					//NOTE: invalid syntax
					else if(*it == '-' || *it == '/' || (*it >= 'A' && *it <= 'Z'))
					{
#ifndef DEBUG_SKIM_SCRIPT
						warning("invalid script syntax [file: %s, section: %s, line: \"%s\"], skipped", _script.c_str(), _section.c_str(), line.c_str());
#endif
						skip_line = true;
					}
					// command name
					else if((*it >= 'a' && *it <= 'z'))
					{
						buffer.clear();
						buffer += *it;

						parse_state = PS_COMMAND_NAME;
					}
					break;

				case PS_COMMAND_NAME:
					// command value
					if(*it == '=')
					{
						command_name = buffer;
						buffer.clear();

						parse_state = PS_COMMAND_VALUE;
					}
					else
						buffer += *it;
					break;

				case PS_COMMAND_VALUE:
					// command value end
					if(*it == ';')
					{
						command_name.trim();
						buffer.trim();

#ifndef DEBUG_SKIM_SCRIPT
						debug("%s=%s;", command_name.c_str(), buffer.c_str());
#endif

						Common::HashMap<Common::String, Common::Error (GagEngine::*)(const Common::String &)>::const_iterator f = _commandCallbacks.find(command_name);
						if(f != _commandCallbacks.end())
						{
							status = (this->*f->_value)(buffer);
							if(status.getCode() != Common::kNoError)
							{
								skip_line = true;
								done = true;
							}
						}

						parse_state = PS_SECTION_BODY;
					}
					else
						buffer += *it;
					break;
				}

				if(skip_line)
					break;
			}

			if(done)
				break;
		}
	}
	else
	{
		status = Common::Error(Common::kReadingFailed, _script + ", open()");
	}

	return status;
}
Пример #6
0
bool WintermuteEngine::getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption) {
	bool retVal = false;
	caption = name = "(invalid)";
	Common::SeekableReadStream *stream = NULL;
	// Quick-fix, instead of possibly breaking the persistence-system, let's just roll with it
	BaseFileManager *fileMan = new BaseFileManager(Common::UNK_LANG);
	fileMan->registerPackages(fslist);
	stream = fileMan->openFile("startup.settings", false, false);

	// The process is as follows: Check the "GAME=" tag in startup.settings, to decide where the
	// game-settings are (usually "default.game"), then look into the game-settings to find
	// the NAME = and CAPTION = tags, to use them to generate a gameid and extras-field

	Common::String settingsGameFile = "default.game";
	// If the stream-open failed, lets at least attempt to open the default game file afterwards
	// so, we don't call it a failure yet.
	if (stream) {
		while (!stream->eos() && !stream->err()) {
			Common::String line = stream->readLine();
			line.trim(); // Get rid of indentation
			// Expect "SETTINGS {" or comment, or empty line
			if (line.size() == 0 || line[0] == ';' || (line.contains("{"))) {
				continue;
			} else {
				// We are looking for "GAME ="
				Common::StringTokenizer token(line, "=");
				Common::String key = token.nextToken();
				Common::String value = token.nextToken();
				if (value.size() == 0) {
					continue;
				}
				if (value[0] == '\"') {
					value.deleteChar(0);
				} else {
					continue;
				}
				if (value.lastChar() == '\"') {
					value.deleteLastChar();
				}
				if (key == "GAME") {
					settingsGameFile = value;
					break;
				}
			}
		}
	}

	delete stream;
	stream = fileMan->openFile(settingsGameFile, false, false);
	if (stream) {
		// We do some manual parsing here, as the engine needs gfx to be initalized to do that.
		while (!stream->eos() && !stream->err()) {
			Common::String line = stream->readLine();
			line.trim(); // Get rid of indentation
			// Expect "GAME {" or comment, or empty line
			if (line.size() == 0 || line[0] == ';' || (line.contains("{"))) {
				continue;
			} else {
				Common::StringTokenizer token(line, "=");
				Common::String key = token.nextToken();
				Common::String value = token.nextToken();
				if (value.size() == 0) {
					continue;
				}
				if (value[0] == '\"') {
					value.deleteChar(0);
				} else {
					continue;    // not a string
				}
				if (value.lastChar() == '\"') {
					value.deleteLastChar();
				}
				if (key == "NAME") {
					retVal = true;
					name = value;
				} else if (key == "CAPTION") {
					retVal = true;
					caption = value;
				}
			}
		}
		delete stream;
	}
	delete fileMan;
	BaseEngine::destroy();
	return retVal;
}
Пример #7
0
void Dialog::show(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2) {
	debug(0, "Dialog::show(%04x, %u:%u, %u:%u)", addr, slot1, animation1, slot2, animation2);
	Resources *res = Resources::instance();
	int n = 0;
	Common::String message;
	byte color = color1;

	if (animation1 != 0) {
		SceneEvent e(SceneEvent::kPlayAnimation);
		e.animation = animation1;
		e.slot = 0xc0 | slot1; //looped, paused
		scene->push(e);
	}

	if (animation2 != 0) {
		SceneEvent e(SceneEvent::kPlayAnimation);
		e.animation = animation2;
		e.slot = 0xc0 | slot2; //looped, paused
		scene->push(e);
	}

	while (n < 4) {
		byte c = res->eseg.get_byte(addr++);
		//debug(0, "%02x: %c", c, c > 0x20? c: '.');

		switch (c) {
		case 0:
			++n;
			switch (n) {
			case 1:
				//debug(0, "new line\n");
				if (!message.empty())
					message += '\n';
				break;
			case 2:
				//debug(0, "displaymessage %s", message.c_str());
				if (color == color2) {
					//pause animation in other slot
					{
						SceneEvent e(SceneEvent::kPauseAnimation);
						e.slot = 0x80 | slot1;
						scene->push(e);
					}
					{
						SceneEvent e(SceneEvent::kPlayAnimation);
						e.animation = animation2;
						e.slot = 0x80 | slot2;
						scene->push(e);
					}
				} else if (color == color1) {
					//pause animation in other slot
					{
						SceneEvent e(SceneEvent::kPauseAnimation);
						e.slot = 0x80 | slot2;
						scene->push(e);
					}
					{
						SceneEvent e(SceneEvent::kPlayAnimation);
						e.animation = animation1;
						e.slot = 0x80 | slot1;
						scene->push(e);
					}
				}

				{
					message.trim();
					if (message.empty())
						break;

					SceneEvent e(SceneEvent::kMessage);
					e.message = message;
					e.color = color;
					if (color == color1)
						e.slot = slot1;
					if (color == color2)
						e.slot = slot2;
					scene->push(e);
					message.clear();
				}
				break;

			case 3:
				color = color == color1 ? color2 : color1;
				//debug(0, "changing color to %02x", color);
				break;
			}
			break;

		case 0xff: {
			//fixme : wait for the next cycle of the animation
		}
		break;

		default:
			message += c;
			n = 0;
		}
	}

	SceneEvent e(SceneEvent::kClearAnimations);
	scene->push(e);
}
Пример #8
0
bool World::loadWorld(Common::MacResManager *resMan) {
	Common::MacResIDArray resArray;
	Common::SeekableReadStream *res;
	Common::MacResIDArray::const_iterator iter;

	// Dumping interpreter code
#if 1
	res = resMan->getResource(MKTAG('C','O','D','E'), 1);
	warning("code size: %d", res->size());
	byte *buf = (byte *)malloc(res->size());
	res->read(buf, res->size());
	Common::DumpFile out;
	out.open("code.bin");
	out.write(buf, res->size());
	out.close();
	free(buf);
	delete res;
#endif

	if ((resArray = resMan->getResIDArray(MKTAG('G','C','O','D'))).size() == 0)
		return false;

	// Load global script
	res = resMan->getResource(MKTAG('G','C','O','D'), resArray[0]);
	_globalScript = new Script(res);

	// TODO: read creator

	// Load main configuration
	if ((resArray = resMan->getResIDArray(MKTAG('V','E','R','S'))).size() == 0)
		return false;

	_name = resMan->getBaseFileName();

	if (resArray.size() > 1)
		warning("Too many VERS resources");

	if (!resArray.empty()) {
		debug(3, "Loading version info");

		res = resMan->getResource(MKTAG('V','E','R','S'), resArray[0]);

		res->skip(10);
		byte b = res->readByte();
		_weaponMenuDisabled = (b != 0);
		if (b != 0 && b != 1)
			error("Unexpected value for weapons menu");

		res->skip(3);
		_aboutMessage = readPascalString(res);

		if (!scumm_stricmp(resMan->getBaseFileName().c_str(), "Scepters"))
			res->skip(1); // ????

		_soundLibrary1 = readPascalString(res);
		_soundLibrary2 = readPascalString(res);

		delete res;
	}

	Common::String *message;
	if ((message = loadStringFromDITL(resMan, 2910, 1)) != NULL) {
		message->trim();
		debug(2, "_gameOverMessage: %s", message->c_str());
		_gameOverMessage = message;
	}
	if ((message = loadStringFromDITL(resMan, 2480, 3)) != NULL) {
		message->trim();
		debug(2, "_saveBeforeQuitMessage: %s", message->c_str());
		_saveBeforeQuitMessage = message;
	}
	if ((message = loadStringFromDITL(resMan, 2490, 3)) != NULL) {
		message->trim();
		debug(2, "_saveBeforeCloseMessage: %s", message->c_str());
		_saveBeforeCloseMessage = message;
	}
	if ((message = loadStringFromDITL(resMan, 2940, 2)) != NULL) {
		message->trim();
		debug(2, "_revertMessage: %s", message->c_str());
		_revertMessage = message;
	}

	// Load scenes
	resArray = resMan->getResIDArray(MKTAG('A','S','C','N'));
	debug(3, "Loading %d scenes", resArray.size());

	for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
		res = resMan->getResource(MKTAG('A','S','C','N'), *iter);
		Scene *scene = new Scene(resMan->getResName(MKTAG('A','S','C','N'), *iter), res);

		res = resMan->getResource(MKTAG('A','C','O','D'), *iter);
		if (res != NULL)
			scene->_script = new Script(res);

		res = resMan->getResource(MKTAG('A','T','X','T'), *iter);
		if (res != NULL) {
			scene->_textBounds = readRect(res);
			scene->_fontType = res->readUint16BE();
			scene->_fontSize = res->readUint16BE();

			Common::String text;
			while (res->pos() < res->size()) {
				char c = res->readByte();
				if (c == 0x0d)
					c = '\n';
				text += c;
			}
			scene->_text = text;

			delete res;
		}
		addScene(scene);
	}

	// Load Objects
	resArray = resMan->getResIDArray(MKTAG('A','O','B','J'));
	debug(3, "Loading %d objects", resArray.size());

	for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
		res = resMan->getResource(MKTAG('A','O','B','J'), *iter);
		addObj(new Obj(resMan->getResName(MKTAG('A','O','B','J'), *iter), res));
	}

	// Load Characters
	resArray = resMan->getResIDArray(MKTAG('A','C','H','R'));
	debug(3, "Loading %d characters", resArray.size());

	for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
		res = resMan->getResource(MKTAG('A','C','H','R'), *iter);
		Chr *chr = new Chr(resMan->getResName(MKTAG('A','C','H','R'), *iter), res);

		addChr(chr);
		// TODO: What if there's more than one player character?
		if (chr->_playerCharacter)
			_player = chr;
	}

	// Load Sounds
	resArray = resMan->getResIDArray(MKTAG('A','S','N','D'));
	debug(3, "Loading %d sounds", resArray.size());

	for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
		res = resMan->getResource(MKTAG('A','S','N','D'), *iter);
		addSound(new Sound(resMan->getResName(MKTAG('A','S','N','D'), *iter), res));
	}

	if (!_soundLibrary1.empty()) {
		loadExternalSounds(_soundLibrary1);
	}
	if (!_soundLibrary2.empty()) {
		loadExternalSounds(_soundLibrary2);
	}

	// Load Patterns
	res = resMan->getResource(MKTAG('P','A','T','#'), 900);
	if (res != NULL) {
		int count = res->readUint16BE();
		debug(3, "Loading %d patterns", count);

		for (int i = 0; i < count; i++) {
			byte *pattern = (byte *)malloc(8);

			res->read(pattern, 8);
			_patterns->push_back(pattern);
		}

		delete res;
	} else {
		/* Enchanted Scepters did not use the PAT# resource for the textures. */
		res = resMan->getResource(MKTAG('C','O','D','E'), 1);
		if (res != NULL) {
			res->skip(0x55ac);
			for (int i = 0; i < 29; i++) {
				byte *pattern = (byte *)malloc(8);

				res->read(pattern, 8);
				_patterns->push_back(pattern);
			}
		}
		delete res;
	}

	res = resMan->getResource(MKTAG('M','E','N','U'), 2001);
	if (res != NULL) {
		Common::StringArray *menu = readMenu(res);
		_aboutMenuItemName.clear();
		Common::String string = menu->operator[](1);

		for (uint i = 0; i < string.size() && string[i] != ';'; i++) // Read token
			_aboutMenuItemName += string[i];

		delete menu;
		delete res;
	}
	res = resMan->getResource(MKTAG('M','E','N','U'), 2004);
	if (res != NULL) {
		Common::StringArray *menu = readMenu(res);
		_commandsMenuName = menu->operator[](0);
		_commandsMenu = menu->operator[](1);
		delete menu;
		delete res;
	}
	res = resMan->getResource(MKTAG('M','E','N','U'), 2005);
	if (res != NULL) {
		Common::StringArray *menu = readMenu(res);
		_weaponsMenuName = menu->operator[](0);
		delete menu;
		delete res;
	}
	// TODO: Read Apple menu and get the name of that menu item..

	// store global info in state object for use with save/load actions
	//world.setCurrentState(initialState);	// pass off the state object to the world

	return true;
}
Пример #9
0
void Lingo::func_mci(Common::String &s) {
	Common::String params[5];
	MCITokenType command = kMCITokenNone;

	s.trim();
	s.toLowercase();

	MCITokenType state = kMCITokenNone;
	Common::String token;
	const char *ptr = s.c_str();
	int respos = -1;

	while (*ptr) {
		while (*ptr && *ptr == ' ')
			ptr++;

		token.clear();

		while (*ptr && *ptr != ' ')
			token += *ptr++;

		switch (state) {
		case kMCITokenNone:
			{
				MCIToken *f = MCITokens;

				while (f->token) {
					if (command == f->command && token == f->token)
						break;

					f++;
				}

				if (command == kMCITokenNone) { // We caught command
					command = f->flag; // Switching to processing this command parameters
				} else if (f->flag == kMCITokenNone) { // Unmatched token, storing as filename
					if (!params[0].empty())
						warning("Duplicate filename in MCI command: %s -> %s", params[0].c_str(), token.c_str());
					params[0] = token;
				} else { // This is normal parameter, storing next token to designated position
					if (f->pos > 0) { // This is normal parameter
						state = f->flag;
						respos = f->pos;
					} else { // This is boolean
						params[-f->pos] = "true";
						state = kMCITokenNone;
					}
				}
				break;
			}
		default:
			params[respos] = token;
			state = kMCITokenNone;
			break;
		}
	}

	switch (command) {
	case kMCITokenOpen:
		{
			warning("MCI open file: %s, type: %s, alias: %s buffer: %s", params[0].c_str(), params[1].c_str(), params[2].c_str(), params[3].c_str());

			Common::File *file = new Common::File();

			if (!file->open(params[0])) {
				warning("Failed to open %s", params[0].c_str());
				delete file;
				return;
			}

			if (params[1] == "waveaudio") {
				Audio::AudioStream *sound = Audio::makeWAVStream(file, DisposeAfterUse::YES);
				_audioAliases[params[2]] = sound;
			} else {
				warning("Unhandled audio type %s", params[2].c_str());
			}
		}
		break;
	case kMCITokenPlay:
		{
			warning("MCI play file: %s, from: %s, to: %s, repeat: %s", params[0].c_str(), params[1].c_str(), params[2].c_str(), params[3].c_str());

			if (!_audioAliases.contains(params[0])) {
				warning("Unknown alias %s", params[0].c_str());
				return;
			}

			uint32 from = strtol(params[1].c_str(), 0, 10);
			uint32 to = strtol(params[2].c_str(), 0, 10);

			_vm->getSoundManager()->playMCI(*_audioAliases[params[0]], from, to);
		}
		break;
	default:
		warning("Unhandled MCI command: %s", s.c_str());
	}
}