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(); }
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(); }
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); } }
void Conf::get(const Common::String &key, Common::String &field, const char *defaultVal) { field = ConfMan.hasKey(key) ? ConfMan.get(key) : defaultVal; field.trim(); }
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; }
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; }
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); }
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; }
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()); } }