/** * Formats AGI string. * This function turns a AGI string into a real string expanding values * according to the AGI format specifiers. * @param s string containing the format specifier * @param n logic number */ char *AgiEngine::agiSprintf(const char *s) { static char agiSprintf_buf[768]; Common::String p; char z[16]; debugC(3, kDebugLevelText, "logic %d, '%s'", _game.lognum, s); while (*s) { switch (*s) { case '%': s++; switch (*s++) { int i; case 'v': i = strtoul(s, NULL, 10); while (*s >= '0' && *s <= '9') s++; sprintf(z, "%015i", getvar(i)); i = 99; if (*s == '|') { s++; i = strtoul(s, NULL, 10); while (*s >= '0' && *s <= '9') s++; } if (i == 99) { // remove all leading 0 // don't remove the 3rd zero if 000 for (i = 0; z[i] == '0' && i < 14; i++) ; } else { i = 15 - i; } safeStrcat(p, z + i); break; case '0': i = strtoul(s, NULL, 10) - 1; safeStrcat(p, objectName(i)); break; case 'g': i = strtoul(s, NULL, 10) - 1; safeStrcat(p, _game.logics[0].texts[i]); break; case 'w': i = strtoul(s, NULL, 10) - 1; safeStrcat(p, _game.egoWords[i].word); break; case 's': i = strtoul(s, NULL, 10); safeStrcat(p, agiSprintf(_game.strings[i])); break; case 'm': i = strtoul(s, NULL, 10) - 1; if (_game.logics[_game.lognum].numTexts > i) safeStrcat(p, agiSprintf(_game.logics[_game.lognum].texts[i])); break; } while (*s >= '0' && *s <= '9') s++; break; case '\\': s++; // FALL THROUGH default: p += *s++; break; } } assert(p.size() < sizeof(agiSprintf_buf)); strcpy(agiSprintf_buf, p.c_str()); return agiSprintf_buf; }
void OneDriveListDirectoryRequest::makeRequest(Common::String url) { Networking::JsonCallback callback = new Common::Callback<OneDriveListDirectoryRequest, Networking::JsonResponse>(this, &OneDriveListDirectoryRequest::listedDirectoryCallback); Networking::ErrorCallback failureCallback = new Common::Callback<OneDriveListDirectoryRequest, Networking::ErrorResponse>(this, &OneDriveListDirectoryRequest::listedDirectoryErrorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _storage->accessToken()); _workingRequest = ConnMan.addRequest(request); }
void Lingo::call(Common::String &name, int nargs) { bool drop = false; Symbol *sym; if (!g_lingo->_handlers.contains(name)) { Symbol *s = g_lingo->lookupVar(name.c_str(), false); if (s && s->type == OBJECT) { debugC(3, kDebugLingoExec, "Dereferencing object reference: %s to %s", name.c_str(), s->u.s->c_str()); name = *s->u.s; } } if (!g_lingo->_handlers.contains(name)) { warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs); drop = true; } else { sym = g_lingo->_handlers[name]; if (sym->type == BLTIN && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) { if (sym->nargs == sym->maxArgs) warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs); else warning("Incorrect number of arguments to handler '%s', expecting %d or %d. Dropping %d stack items", name.c_str(), sym->nargs, sym->maxArgs, nargs); drop = true; } } if (drop) { for (int i = 0; i < nargs; i++) g_lingo->pop(); // Push dummy value g_lingo->pushVoid(); return; } if (sym->nargs != -1 && sym->nargs < nargs) { warning("Incorrect number of arguments for function %s. Dropping extra %d", name.c_str(), nargs - sym->nargs); for (int i = 0; i < nargs - sym->nargs; i++) g_lingo->pop(); } if (sym->type == BLTIN) { if (sym->u.bltin == b_factory) g_lingo->factoryCall(name, nargs); else (*sym->u.bltin)(nargs); return; } for (int i = nargs; i < sym->nargs; i++) { Datum d; d.u.s = NULL; d.type = VOID; g_lingo->push(d); } debugC(5, kDebugLingoExec, "Pushing frame %d", g_lingo->_callstack.size() + 1); CFrame *fp = new CFrame; fp->sp = sym; fp->retpc = g_lingo->_pc; fp->retscript = g_lingo->_currentScript; fp->localvars = g_lingo->_localvars; // Create new set of local variables g_lingo->_localvars = new SymbolHash; g_lingo->_callstack.push_back(fp); g_lingo->_currentScript = sym->u.defn; g_lingo->execute(0); g_lingo->_returning = false; }
void OSpit::xbookclick(const ArgumentArray &args) { // Let's hook onto our video RivenVideo *video = _vm->_video->getSlot(args[0]); // Convert from the standard QuickTime base time to milliseconds // The values are in terms of 1/600 of a second. // Have I said how much I just *love* QuickTime? </sarcasm> uint32 startTime = args[1] * 1000 / 600; uint32 endTime = args[2] * 1000 / 600; // Track down our hotspot Common::String hotspotName = Common::String::format("touchBook%d", args[3]); RivenHotspot *hotspot = _vm->getCard()->getHotspotByName(hotspotName); Common::Rect hotspotRect = hotspot->getRect(); debug(0, "xbookclick:"); debug(0, "\tVideo Code = %d", args[0]); debug(0, "\tStart Time = %dms", startTime); debug(0, "\tEnd Time = %dms", endTime); debug(0, "\tHotspot = %d -> %s", args[3], hotspotName.c_str()); // Just let the video play while we wait until Gehn opens the trap book for us while (video->getTime() < startTime && !_vm->hasGameEnded()) { _vm->doFrame(); } // Break out if we're quitting if (_vm->hasGameEnded()) return; // OK, Gehn has opened the trap book and has asked us to go in. Let's watch // and see what the player will do... while (video->getTime() < endTime && !_vm->hasGameEnded()) { if (hotspotRect.contains(getMousePosition())) _vm->_cursor->setCursor(kRivenOpenHandCursor); else _vm->_cursor->setCursor(kRivenMainCursor); if (mouseIsDown()) { if (hotspotRect.contains(getMousePosition())) { // OK, we've used the trap book! We go for ride lady! _vm->_video->closeVideos(); // Stop all videos _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor _vm->_gfx->scheduleTransition(kRivenTransitionBlend); _vm->getCard()->drawPicture(3); // Black out the screen _vm->_sound->playSound(0); // Play the link sound _vm->delay(12000); _vm->getCard()->playMovie(7); // Activate Gehn Link Video RivenVideo *linkVideo = _vm->_video->openSlot(1); // Play Gehn Link Video linkVideo->playBlocking(); _vm->_vars["ocage"] = 1; _vm->_vars["agehn"] = 4; // Set Gehn to the trapped state _vm->_vars["atrapbook"] = 1; // We've got the trap book again _vm->_sound->playSound(0); // Play the link sound again _vm->_gfx->scheduleTransition(kRivenTransitionBlend); _vm->changeToCard(_vm->getStack()->getCardStackId(0x2885)); // Link out! _vm->_inventory->forceVisible(true); _vm->delay(2000); _vm->_inventory->forceVisible(false); _vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage) return; } } _vm->doFrame(); } // Break out if we're quitting if (_vm->hasGameEnded()) return; // If there was no click and this is the third time Gehn asks us to // use the trap book, he will shoot the player. Dead on arrival. // Run the credits from here. if (_vm->_vars["agehn"] == 3) { _vm->_scriptMan->stopAllScripts(); runCredits(args[0], 5000); return; } // There was no click, so just play the rest of the video. video->playBlocking(); }
void MinigameBbAnt::loadSounds() { for (uint i = 0; i < kSoundFilenamesCount; ++i) { Common::String filename = Common::String::format("bbant/%s", kSoundFilenames[i]); _vm->_sound->loadSound(filename.c_str()); } }
const char *slide() const { return _slide.c_str(); }
// TODO: specify the possible return values here static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const Common::String &edebuglevels) { // Determine the game data path, for validation and error messages Common::FSNode dir(ConfMan.get("path")); Common::Error err = Common::kNoError; Engine *engine = 0; // Verify that the game path refers to an actual directory if (!(dir.exists() && dir.isDirectory())) err = Common::kPathNotDirectory; // Create the game engine if (err.getCode() == Common::kNoError) err = (*plugin)->createInstance(&system, &engine); // Check for errors if (!engine || err.getCode() != Common::kNoError) { // Print a warning; note that scummvm_main will also // display an error dialog, so we don't have to do this here. warning("%s failed to instantiate engine: %s (target '%s', path '%s')", plugin->getName(), err.getDesc().c_str(), ConfMan.getActiveDomainName().c_str(), dir.getPath().c_str() ); // Autoadded is set only when no path was provided and // the game is run from command line. // // Thus, we remove this garbage entry // // Fixes bug #1544799 if (ConfMan.hasKey("autoadded")) { ConfMan.removeGameDomain(ConfMan.getActiveDomainName().c_str()); } return err; } // Set the window caption to the game name Common::String caption(ConfMan.get("description")); if (caption.empty()) { caption = EngineMan.findGame(ConfMan.get("gameid")).description(); } if (caption.empty()) caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name if (!caption.empty()) { system.setWindowCaption(caption.c_str()); } // // Setup various paths in the SearchManager // // Add the game path to the directory search list SearchMan.addDirectory(dir.getPath(), dir, 0, 4); // Add extrapath (if any) to the directory search list if (ConfMan.hasKey("extrapath")) { dir = Common::FSNode(ConfMan.get("extrapath")); SearchMan.addDirectory(dir.getPath(), dir); } // If a second extrapath is specified on the app domain level, add that as well. if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationDomain)) { dir = Common::FSNode(ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain)); SearchMan.addDirectory(dir.getPath(), dir); } // On creation the engine should have set up all debug levels so we can use // the command line arugments here Common::StringTokenizer tokenizer(edebuglevels, " ,"); while (!tokenizer.empty()) { Common::String token = tokenizer.nextToken(); if (!DebugMan.enableDebugChannel(token)) warning(_("Engine does not support debug level '%s'"), token.c_str()); } // Inform backend that the engine is about to be run system.engineInit(); // Run the engine Common::Error result = engine->run(); // Inform backend that the engine finished system.engineDone(); // Free up memory delete engine; // We clear all debug levels again even though the engine should do it DebugMan.clearAllDebugChannels(); // Reset the file/directory mappings SearchMan.clear(); // Return result (== 0 means no error) return result; }
Common::Error Saver::restore(int slot) { assert(!getMacroRestoreFlag()); Common::StackLock slock1(g_globals->_soundManager._serverDisabledMutex); // Signal any objects registered for notification _loadNotifiers.notify(false); // Set fields _macroRestoreFlag = true; _saveSlot = slot; _unresolvedPtrs.clear(); // Set up the serializer Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(g_vm->generateSaveName(slot)); if (!saveFile) return Common::kReadingFailed; Serializer serializer(saveFile, NULL); // Read in the savegame header tSageSavegameHeader header; readSavegameHeader(saveFile, header); if (header.thumbnail) header.thumbnail->free(); delete header.thumbnail; serializer.setSaveVersion(header.version); // Load in data for objects that need to come at the start of the savegame for (Common::List<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) { (*i)->listenerSynchronize(serializer); } // Loop through each registered object to load in the data for (SynchronizedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) { serializer.validate((*i)->getClassName()); (*i)->synchronize(serializer); } // Loop through the remaining data of the file, instantiating new objects. // Note: I don't store pointers to instantiated objects here, because it's not necessary - the mere act // of instantiating a saved object registers it with the saver, and will then be resolved to whatever // object originally had a pointer to it as part of the post-processing step Common::String className; serializer.syncString(className); while (className != "END") { SavedObject *savedObject; if (!_factoryPtr || ((savedObject = _factoryPtr(className)) == NULL)) error("Unknown class name '%s' encountered trying to restore savegame", className.c_str()); // Populate the contents of the object savedObject->synchronize(serializer); // Move to next object serializer.syncString(className); } // Post-process any unresolved pointers to get the correct pointer resolveLoadPointers(); delete saveFile; // Final post-restore notifications _macroRestoreFlag = false; _loadNotifiers.notify(true); return Common::kNoError; }
Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage requestedLanguage, kLanguage *secondaryLanguage, uint16 *languageSplitter) const { kLanguage foundLanguage = K_LANG_NONE; const byte *textPtr = (const byte *)str.c_str(); byte curChar = 0; byte curChar2 = 0; while (1) { curChar = *textPtr; if (!curChar) break; if ((curChar == '%') || (curChar == '#')) { curChar2 = *(textPtr + 1); foundLanguage = charToLanguage(curChar2); if (foundLanguage != K_LANG_NONE) { // Return language splitter if (languageSplitter) *languageSplitter = curChar | ( curChar2 << 8 ); // Return the secondary language found in the string if (secondaryLanguage) *secondaryLanguage = foundLanguage; break; } } textPtr++; } if (foundLanguage == requestedLanguage) { if (curChar2 == 'J') { // Japanese including Kanji, displayed with system font // Convert half-width characters to full-width equivalents Common::String fullWidth; uint16 mappedChar; textPtr += 2; // skip over language splitter while (1) { curChar = *textPtr; switch (curChar) { case 0: // Terminator NUL return fullWidth; case '\\': // "\n", "\N", "\r" and "\R" were overwritten with SPACE + 0x0D in PC-9801 SSCI // inside GetLongest() (text16). We do it here, because it's much cleaner and // we have to process the text here anyway. // Occurs for example in Police Quest 2 intro curChar2 = *(textPtr + 1); switch (curChar2) { case 'n': case 'N': case 'r': case 'R': fullWidth += ' '; fullWidth += 0x0D; // CR textPtr += 2; continue; } } textPtr++; mappedChar = s_halfWidthSJISMap[curChar]; if (mappedChar) { fullWidth += mappedChar >> 8; fullWidth += mappedChar & 0xFF; } else { // Copy double-byte character curChar2 = *(textPtr++); if (!curChar) { error("SJIS character %02X is missing second byte", curChar); break; } fullWidth += curChar; fullWidth += curChar2; } } } else {
static bool isValidDomainName(const Common::String &domName) { const char *p = domName.c_str(); while (*p && (Common::isAlnum(*p) || *p == '-' || *p == '_')) p++; return *p == 0; }
void MohawkEngine_CSTime::loadResourceFile(Common::String name) { MohawkArchive *archive = new MohawkArchive(); if (!archive->open(name + ".mhk")) error("failed to open %s.mhk", name.c_str()); _mhk.push_back(archive); }
void ScriptLifeV1::SAY_MESSAGE_OBJ() { byte actor = getParamByte(); uint16 id = getParamUint16(); Common::String str = g_resource->getMessage(0, id); warning("STUB: SAY_MESSAGE_OBJ(%d): %s", id, str.c_str()); }
const char *ToltecsEngine::getSavegameFilename(int num) { static Common::String filename; filename = getSavegameFilename(_targetName, num); return filename.c_str(); }
Common::Error ToltecsEngine::saveGameState(int slot, const Common::String &description) { const char *fileName = getSavegameFilename(slot); savegame(fileName, description.c_str()); return Common::kNoError; }
const char *location() const { return _location.c_str(); }
bool NSArchive::hasFile(const Common::String &name) const { if (name.empty()) return false; return lookup(name.c_str()) != _numFiles; }
const char *character() const { return _character.c_str(); }
void ConsoleDialog::handleKeyDown(Common::KeyState state) { int i; if (_slideMode != kNoSlideMode) return; switch (state.keycode) { case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: { if (_caretVisible) drawCaret(true); nextLine(); assert(_promptEndPos >= _promptStartPos); int len = _promptEndPos - _promptStartPos; bool keepRunning = true; if (len > 0) { // We have to allocate the string buffer with new, since VC++ sadly does not // comply to the C++ standard, so we can't use a dynamic sized stack array. char *str = new char[len + 1]; // Copy the user input to str for (i = 0; i < len; i++) str[i] = buffer(_promptStartPos + i); str[len] = '\0'; // Add the input to the history addToHistory(str); // Pass it to the input callback, if any if (_callbackProc) keepRunning = (*_callbackProc)(this, str, _callbackRefCon); // Get rid of the string buffer delete[] str; } print(PROMPT); _promptStartPos = _promptEndPos = _currentPos; draw(); if (!keepRunning) slideUpAndClose(); break; } case Common::KEYCODE_ESCAPE: slideUpAndClose(); break; case Common::KEYCODE_BACKSPACE: if (_caretVisible) drawCaret(true); if (_currentPos > _promptStartPos) { _currentPos--; killChar(); } scrollToCurrent(); drawLine(pos2line(_currentPos)); break; case Common::KEYCODE_TAB: { if (_completionCallbackProc) { int len = _currentPos - _promptStartPos; assert(len >= 0); char *str = new char[len + 1]; // Copy the user input to str for (i = 0; i < len; i++) str[i] = buffer(_promptStartPos + i); str[len] = '\0'; Common::String completion; if ((*_completionCallbackProc)(this, str, completion, _callbackRefCon)) { if (_caretVisible) drawCaret(true); insertIntoPrompt(completion.c_str()); scrollToCurrent(); drawLine(pos2line(_currentPos)); } delete[] str; } break; } // Keypad & special keys // - if num lock is set, we always go to the default case // - if num lock is not set, we either fall down to the special key case // or ignore the key press in case of 0 (INSERT) or 5 case Common::KEYCODE_KP0: case Common::KEYCODE_KP5: if (state.flags & Common::KBD_NUM) defaultKeyDownHandler(state); break; case Common::KEYCODE_KP_PERIOD: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_DELETE: if (_currentPos < _promptEndPos) { killChar(); drawLine(pos2line(_currentPos)); } break; case Common::KEYCODE_KP1: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_END: if (state.hasFlags(Common::KBD_SHIFT)) { _scrollLine = _promptEndPos / kCharsPerLine; if (_scrollLine < _linesPerPage - 1) _scrollLine = _linesPerPage - 1; updateScrollBuffer(); } else { _currentPos = _promptEndPos; } draw(); break; case Common::KEYCODE_KP2: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_DOWN: historyScroll(-1); break; case Common::KEYCODE_KP3: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_PAGEDOWN: if (state.hasFlags(Common::KBD_SHIFT)) { _scrollLine += _linesPerPage - 1; if (_scrollLine > _promptEndPos / kCharsPerLine) { _scrollLine = _promptEndPos / kCharsPerLine; if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1) _scrollLine = _firstLineInBuffer + _linesPerPage - 1; } updateScrollBuffer(); draw(); } break; case Common::KEYCODE_KP4: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_LEFT: if (_currentPos > _promptStartPos) _currentPos--; drawLine(pos2line(_currentPos)); break; case Common::KEYCODE_KP6: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_RIGHT: if (_currentPos < _promptEndPos) _currentPos++; drawLine(pos2line(_currentPos)); break; case Common::KEYCODE_KP7: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_HOME: if (state.hasFlags(Common::KBD_SHIFT)) { _scrollLine = _firstLineInBuffer + _linesPerPage - 1; updateScrollBuffer(); } else { _currentPos = _promptStartPos; } draw(); break; case Common::KEYCODE_KP8: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_UP: historyScroll(+1); break; case Common::KEYCODE_KP9: if (state.flags & Common::KBD_NUM) { defaultKeyDownHandler(state); break; } case Common::KEYCODE_PAGEUP: if (state.hasFlags(Common::KBD_SHIFT)) { _scrollLine -= _linesPerPage - 1; if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1) _scrollLine = _firstLineInBuffer + _linesPerPage - 1; updateScrollBuffer(); draw(); } break; default: defaultKeyDownHandler(state); } }
// TODO: specify the possible return values here static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const Common::String &edebuglevels) { // Determine the game data path, for validation and error messages Common::FSNode dir(ConfMan.get("path")); Common::Error err = Common::kNoError; Engine *engine = 0; #if defined(SDL_BACKEND) && defined(USE_OPENGL) && defined(USE_RGB_COLOR) // HACK: We set up the requested graphics mode setting here to allow the // backend to switch from Surface SDL to OpenGL if necessary. This is // needed because otherwise the g_system->getSupportedFormats might return // bad values. g_system->beginGFXTransaction(); g_system->setGraphicsMode(ConfMan.get("gfx_mode").c_str()); if (g_system->endGFXTransaction() != OSystem::kTransactionSuccess) { warning("Switching graphics mode to '%s' failed", ConfMan.get("gfx_mode").c_str()); return Common::kUnknownError; } #endif // Verify that the game path refers to an actual directory if (!dir.exists()) { err = Common::kPathDoesNotExist; } else if (!dir.isDirectory()) { err = Common::kPathNotDirectory; } // Create the game engine if (err.getCode() == Common::kNoError) { // Set default values for all of the custom engine options // Appareantly some engines query them in their constructor, thus we // need to set this up before instance creation. const ExtraGuiOptions engineOptions = (*plugin)->getExtraGuiOptions(Common::String()); for (uint i = 0; i < engineOptions.size(); i++) { ConfMan.registerDefault(engineOptions[i].configOption, engineOptions[i].defaultState); } err = (*plugin)->createInstance(&system, &engine); } // Check for errors if (!engine || err.getCode() != Common::kNoError) { // Print a warning; note that scummvm_main will also // display an error dialog, so we don't have to do this here. warning("%s failed to instantiate engine: %s (target '%s', path '%s')", plugin->getName(), err.getDesc().c_str(), ConfMan.getActiveDomainName().c_str(), dir.getPath().c_str() ); // Autoadded is set only when no path was provided and // the game is run from command line. // // Thus, we remove this garbage entry // // Fixes bug #1544799 if (ConfMan.hasKey("autoadded")) { ConfMan.removeGameDomain(ConfMan.getActiveDomainName().c_str()); } return err; } // Set the window caption to the game name Common::String caption(ConfMan.get("description")); if (caption.empty()) { caption = EngineMan.findGame(ConfMan.get("gameid")).description(); } if (caption.empty()) caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name if (!caption.empty()) { system.setWindowCaption(caption.c_str()); } // // Setup various paths in the SearchManager // // Add the game path to the directory search list engine->initializePath(dir); // Add extrapath (if any) to the directory search list if (ConfMan.hasKey("extrapath")) { dir = Common::FSNode(ConfMan.get("extrapath")); SearchMan.addDirectory(dir.getPath(), dir); } // If a second extrapath is specified on the app domain level, add that as well. // However, since the default hasKey() and get() check the app domain level, // verify that it's not already there before adding it. The search manager will // check for that too, so this check is mostly to avoid a warning message. if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationDomain)) { Common::String extraPath = ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain); if (!SearchMan.hasArchive(extraPath)) { dir = Common::FSNode(extraPath); SearchMan.addDirectory(dir.getPath(), dir); } } // On creation the engine should have set up all debug levels so we can use // the command line arguments here Common::StringTokenizer tokenizer(edebuglevels, " ,"); while (!tokenizer.empty()) { Common::String token = tokenizer.nextToken(); if (token.equalsIgnoreCase("all")) DebugMan.enableAllDebugChannels(); else if (!DebugMan.enableDebugChannel(token)) warning(_("Engine does not support debug level '%s'"), token.c_str()); } // Initialize any game-specific keymaps engine->initKeymap(); // Inform backend that the engine is about to be run system.engineInit(); // Run the engine Common::Error result = engine->run(); // Inform backend that the engine finished system.engineDone(); // Clean up any game-specific keymaps engine->deinitKeymap(); // Free up memory delete engine; // We clear all debug levels again even though the engine should do it DebugMan.clearAllDebugChannels(); // Reset the file/directory mappings SearchMan.clear(); // Return result (== 0 means no error) return result; }
bool Console::Cmd_Infos(int argc, const char **argv) { uint16 nodeId = _vm->_state->getLocationNode(); uint32 roomId = _vm->_state->getLocationRoom(); if (argc >= 2) { nodeId = atoi(argv[1]); } if (argc >= 3) { roomId = _vm->_db->getRoomId(argv[2]); if (roomId == 0) { debugPrintf("Unknown room name %s\n", argv[2]); return true; } } NodePtr nodeData = _vm->_db->getNodeData(nodeId, roomId); if (!nodeData) { debugPrintf("No node with id %d\n", nodeId); return true; } Common::String roomName = _vm->_db->getRoomName(roomId); debugPrintf("node: %s %d ", roomName.c_str(), nodeId); for (uint i = 0; i < nodeData->scripts.size(); i++) { debugPrintf("\ninit %d > %s (%s)\n", i, _vm->_state->describeCondition(nodeData->scripts[i].condition).c_str(), _vm->_state->evaluate(nodeData->scripts[i].condition) ? "true" : "false"); describeScript(nodeData->scripts[i].script); } for (uint i = 0; i < nodeData->hotspots.size(); i++) { debugPrintf("\nhotspot %d > %s (%s)\n", i, _vm->_state->describeCondition(nodeData->hotspots[i].condition).c_str(), _vm->_state->evaluate(nodeData->hotspots[i].condition) ? "true" : "false"); for(uint j = 0; j < nodeData->hotspots[i].rects.size(); j++) { PolarRect &rect = nodeData->hotspots[i].rects[j]; debugPrintf(" rect > pitch: %d heading: %d width: %d height: %d\n", rect.centerPitch, rect.centerHeading, rect.width, rect.height); } describeScript(nodeData->hotspots[i].script); } for (uint i = 0; i < nodeData->soundScripts.size(); i++) { debugPrintf("\nsound %d > %s (%s)\n", i, _vm->_state->describeCondition(nodeData->soundScripts[i].condition).c_str(), _vm->_state->evaluate(nodeData->soundScripts[i].condition) ? "true" : "false"); describeScript(nodeData->soundScripts[i].script); } for (uint i = 0; i < nodeData->backgroundSoundScripts.size(); i++) { debugPrintf("\nbackground sound %d > %s (%s)\n", i, _vm->_state->describeCondition(nodeData->backgroundSoundScripts[i].condition).c_str(), _vm->_state->evaluate(nodeData->backgroundSoundScripts[i].condition) ? "true" : "false"); describeScript(nodeData->backgroundSoundScripts[i].script); } return true; }
extern "C" int scummvm_main(int argc, const char * const argv[]) { Common::String specialDebug; Common::String command; // Verify that the backend has been initialized (i.e. g_system has been set). assert(g_system); OSystem &system = *g_system; // Register config manager defaults Base::registerDefaults(); // Parse the command line Common::StringMap settings; command = Base::parseCommandLine(settings, argc, argv); // Load the config file (possibly overridden via command line): if (settings.contains("config")) { ConfMan.loadConfigFile(settings["config"]); settings.erase("config"); } else { ConfMan.loadDefaultConfigFile(); } // Update the config file ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationDomain); // Load and setup the debuglevel and the debug flags. We do this at the // soonest possible moment to ensure debug output starts early on, if // requested. if (settings.contains("debuglevel")) { gDebugLevel = (int)strtol(settings["debuglevel"].c_str(), 0, 10); printf("Debuglevel (from command line): %d\n", gDebugLevel); settings.erase("debuglevel"); // This option should not be passed to ConfMan. } else if (ConfMan.hasKey("debuglevel")) gDebugLevel = ConfMan.getInt("debuglevel"); if (settings.contains("debugflags")) { specialDebug = settings["debugflags"]; settings.erase("debugflags"); } PluginManager::instance().init(); PluginManager::instance().loadAllPlugins(); // load plugins for cached plugin manager // If we received an invalid music parameter via command line we check this here. // We can't check this before loading the music plugins. // On the other hand we cannot load the plugins before we know the file paths (in case of external plugins). if (settings.contains("music-driver")) { if (MidiDriver::getMusicType(MidiDriver::getDeviceHandle(settings["music-driver"])) == MT_INVALID) { warning("Unrecognized music driver '%s'. Switching to default device", settings["music-driver"].c_str()); settings["music-driver"] = "auto"; } } // Process the remaining command line settings. Must be done after the // config file and the plugins have been loaded. Common::Error res; // TODO: deal with settings that require plugins to be loaded res = Base::processSettings(command, settings); if (res.getCode() != Common::kArgumentNotProcessed) { warning("%s", res.getDesc().c_str()); return res.getCode(); } // Init the backend. Must take place after all config data (including // the command line params) was read. system.initBackend(); // If we received an invalid graphics mode parameter via command line // we check this here. We can't do it until after the backend is inited, // or there won't be a graphics manager to ask for the supported modes. if (settings.contains("gfx-mode")) { const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); Common::String option = settings["gfx-mode"]; bool isValid = false; while (gm->name && !isValid) { isValid = !scumm_stricmp(gm->name, option.c_str()); gm++; } if (!isValid) { warning("Unrecognized graphics mode '%s'. Switching to default mode", option.c_str()); settings["gfx-mode"] = "default"; } } setupGraphics(system); // Init the different managers that are used by the engines. // Do it here to prevent fragmentation later system.getAudioCDManager(); MusicManager::instance(); Common::DebugManager::instance(); // Init the event manager. As the virtual keyboard is loaded here, it must // take place after the backend is initiated and the screen has been setup system.getEventManager()->init(); // Directly after initializing the event manager, we will initialize our // event recorder. // // TODO: This is just to match the current behavior, when we further extend // our event recorder, we might do this at another place. Or even change // the whole API for that ;-). g_eventRec.init(); // Now as the event manager is created, setup the keymapper setupKeymapper(system); // Unless a game was specified, show the launcher dialog if (0 == ConfMan.getActiveDomain()) launcherDialog(); // FIXME: We're now looping the launcher. This, of course, doesn't // work as well as it should. In theory everything should be destroyed // cleanly, so this is now enabled to encourage people to fix bits :) while (0 != ConfMan.getActiveDomain()) { // Try to find a plugin which feels responsible for the specified game. const EnginePlugin *plugin = detectPlugin(); if (plugin) { // Unload all plugins not needed for this game, // to save memory PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, plugin); // Try to run the game Common::Error result = runGame(plugin, system, specialDebug); #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES) // do our best to prevent fragmentation by unloading as soon as we can PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); // reallocate the config manager to get rid of any fragmentation ConfMan.defragment(); #endif // Did an error occur ? if (result.getCode() != Common::kNoError) { // Shows an informative error dialog if starting the selected game failed. GUI::displayErrorDialog(result, _("Error running game:")); } // Quit unless an error occurred, or Return to launcher was requested #ifndef FORCE_RTL if (result.getCode() == Common::kNoError && !g_system->getEventManager()->shouldRTL()) break; #endif // Reset RTL flag in case we want to load another engine g_system->getEventManager()->resetRTL(); #ifdef FORCE_RTL g_system->getEventManager()->resetQuit(); #endif // Discard any command line options. It's unlikely that the user // wanted to apply them to *all* games ever launched. ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear(); // Clear the active config domain ConfMan.setActiveDomain(""); PluginManager::instance().loadAllPlugins(); // only for cached manager } else { GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game")); } // reset the graphics to default setupGraphics(system); launcherDialog(); } PluginManager::instance().unloadAllPlugins(); PluginManager::destroy(); GUI::GuiManager::destroy(); Common::ConfigManager::destroy(); Common::SearchManager::destroy(); #ifdef USE_TRANSLATION Common::TranslationManager::destroy(); #endif return 0; }
bool OSystem_Android::openUrl(const Common::String &url) { return JNI::openUrl(url.c_str()); }
/** * DoSave */ static void DoSave() { Common::OutSaveFile *f; char tmpName[FNAMELEN]; // Next getList() must do its stuff again NeedLoad = true; if (SaveSceneName == NULL) { // Generate a new unique save name int i; int ano = 1; // Allocated number while (1) { Common::String fname = _vm->getSavegameFilename(ano); strcpy(tmpName, fname.c_str()); for (i = 0; i < numSfiles; i++) if (!strcmp(savedFiles[i].name, tmpName)) break; if (i == numSfiles) break; ano++; } SaveSceneName = tmpName; } if (SaveSceneDesc[0] == 0) SaveSceneDesc = "unnamed"; f = _vm->getSaveFileMan()->openForSaving(SaveSceneName); Common::Serializer s(0, f); if (f == NULL) goto save_failure; // Write out a savegame header SaveGameHeader hdr; hdr.id = SAVEGAME_ID; hdr.size = SAVEGAME_HEADER_SIZE; hdr.ver = CURRENT_VER; memcpy(hdr.desc, SaveSceneDesc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; g_system->getTimeAndDate(hdr.dateTime); if (!syncSaveGameHeader(s, hdr) || f->err()) { goto save_failure; } DoSync(s); // Write out the special Id for Discworld savegames f->writeUint32LE(0xFEEDFACE); if (f->err()) goto save_failure; f->finalize(); delete f; SaveSceneName = NULL; // Invalidate save name return; save_failure: if (f) { delete f; _vm->getSaveFileMan()->removeSavefile(SaveSceneName); SaveSceneName = NULL; // Invalidate save name } GUI::MessageDialog dialog("Failed to save game state to file."); dialog.runModal(); }
void SaveFileManager::remove(const Common::String &target, int slot) { Common::String filename = Common::String::format("%s.%03d", target.c_str(), slot); g_system->getSavefileManager()->removeSavefile(filename); }
void BladeRunnerEngine::ISez(const Common::String &str) { debug("\t%s", str.c_str()); }
Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(engine); const ADGameDescription *agdDesc = 0; Common::Language language = Common::UNK_LANG; Common::Platform platform = Common::kPlatformUnknown; Common::String extra; if (ConfMan.hasKey("language")) language = Common::parseLanguage(ConfMan.get("language")); if (ConfMan.hasKey("platform")) platform = Common::parsePlatform(ConfMan.get("platform")); if (_flags & kADFlagUseExtraAsHint) { if (ConfMan.hasKey("extra")) extra = ConfMan.get("extra"); } Common::String gameid = ConfMan.get("gameid"); Common::String path; if (ConfMan.hasKey("path")) { path = ConfMan.get("path"); } else { path = "."; // This situation may happen only when game was // launched from a command line with wrong target and // no path was provided. // // A dummy entry will get created and will keep game path // We mark this entry, so it will not be added to the // config file. // // Fixes bug #1544799 ConfMan.setBool("autoadded", true); warning("No path was provided. Assuming the data files are in the current directory"); } Common::FSNode dir(path); Common::FSList files; if (!dir.isDirectory() || !dir.getChildren(files, Common::FSNode::kListAll, true)) { warning("Game data path does not exist or is not a directory (%s)", path.c_str()); return Common::kNoGameDataFoundError; } if (files.empty()) return Common::kNoGameDataFoundError; // Compose a hashmap of all files in fslist. FileMap allFiles; composeFileHashMap(allFiles, files, (_maxScanDepth == 0 ? 1 : _maxScanDepth)); // Run the detector on this ADGameDescList matches = detectGame(files.begin()->getParent(), allFiles, language, platform, extra); if (cleanupPirated(matches)) return Common::kNoGameDataFoundError; if (_singleId == NULL) { // Find the first match with correct gameid. for (uint i = 0; i < matches.size(); i++) { if (matches[i]->gameId == gameid) { agdDesc = matches[i]; break; } } } else if (matches.size() > 0) { agdDesc = matches[0]; } if (agdDesc == 0) { // Use fallback detector if there were no matches by other means agdDesc = fallbackDetect(allFiles, files); if (agdDesc != 0) { // Seems we found a fallback match. But first perform a basic // sanity check: the gameid must match. if (_singleId == NULL && agdDesc->gameId != gameid) agdDesc = 0; } } if (agdDesc == 0) return Common::kNoGameDataFoundError; // If the GUI options were updated, we catch this here and update them in the users config // file transparently. Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc->language); if (agdDesc->flags & ADGF_ADDENGLISH) lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY); Common::updateGameGUIOptions(agdDesc->guiOptions + _guiOptions, lang); GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc, _gameIds); bool showTestingWarning = false; #ifdef RELEASE_BUILD showTestingWarning = true; #endif if (((gameDescriptor.getSupportLevel() == kUnstableGame || (gameDescriptor.getSupportLevel() == kTestingGame && showTestingWarning))) && !Engine::warnUserAboutUnsupportedGame()) return Common::kUserCanceled; debug(2, "Running %s", gameDescriptor.description().c_str()); initSubSystems(agdDesc); if (!createInstance(syst, engine, agdDesc)) return Common::kNoGameDataFoundError; else return Common::kNoError; }
bool Character::loadTalkAnimation(Common::String animName) { debugC(1, kDebugCharacter, "loadTalkAnimation(%s)", animName.c_str()); delete _talkAnim; _talkAnim = new Animation(_vm); return _talkAnim->loadAnimation(animName); }
ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const { ADFilePropertiesMap filesProps; const ADGameFileDescription *fileDesc; const ADGameDescription *g; const byte *descPtr; debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); // Check which files are included in some ADGameDescription *and* are present. // Compute MD5s and file sizes for these files. for (descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != 0; descPtr += _descItemSize) { g = (const ADGameDescription *)descPtr; for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { Common::String fname = fileDesc->fileName; ADFileProperties tmp; if (filesProps.contains(fname)) continue; if (getFileProperties(parent, allFiles, *g, fname, tmp)) { debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str()); filesProps[fname] = tmp; } } } ADGameDescList matched; int maxFilesMatched = 0; bool gotAnyMatchesWithAllFiles = false; // MD5 based matching uint i; for (i = 0, descPtr = _gameDescriptors; ((const ADGameDescription *)descPtr)->gameId != 0; descPtr += _descItemSize, ++i) { g = (const ADGameDescription *)descPtr; bool fileMissing = false; // Do not even bother to look at entries which do not have matching // language and platform (if specified). if ((language != Common::UNK_LANG && g->language != Common::UNK_LANG && g->language != language && !(language == Common::EN_ANY && (g->flags & ADGF_ADDENGLISH))) || (platform != Common::kPlatformUnknown && g->platform != Common::kPlatformUnknown && g->platform != platform)) { continue; } if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra) continue; bool allFilesPresent = true; int curFilesMatched = 0; // Try to match all files for this game for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) { Common::String tstr = fileDesc->fileName; if (!filesProps.contains(tstr)) { fileMissing = true; allFilesPresent = false; break; } if (fileDesc->md5 != NULL && fileDesc->md5 != filesProps[tstr].md5) { debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesProps[tstr].md5.c_str()); fileMissing = true; break; } if (fileDesc->fileSize != -1 && fileDesc->fileSize != filesProps[tstr].size) { debug(3, "Size Mismatch. Skipping"); fileMissing = true; break; } debug(3, "Matched file: %s", tstr.c_str()); curFilesMatched++; } // We found at least one entry with all required files present. // That means that we got new variant of the game. // // Without this check we would have erroneous checksum display // where only located files will be enlisted. // // Potentially this could rule out variants where some particular file // is really missing, but the developers should better know about such // cases. if (allFilesPresent) gotAnyMatchesWithAllFiles = true; if (!fileMissing) { debug(2, "Found game: %s (%s %s/%s) (%d)", g->gameId, g->extra, getPlatformDescription(g->platform), getLanguageDescription(g->language), i); if (curFilesMatched > maxFilesMatched) { debug(2, " ... new best match, removing all previous candidates"); maxFilesMatched = curFilesMatched; matched.clear(); // Remove any prior, lower ranked matches. matched.push_back(g); } else if (curFilesMatched == maxFilesMatched) { matched.push_back(g); } else { debug(2, " ... skipped"); } } else { debug(5, "Skipping game: %s (%s %s/%s) (%d)", g->gameId, g->extra, getPlatformDescription(g->platform), getLanguageDescription(g->language), i); } } // We didn't find a match if (matched.empty()) { if (!filesProps.empty() && gotAnyMatchesWithAllFiles) { reportUnknown(parent, filesProps); } // Filename based fallback } return matched; }
void LabEngine::processMonitor(const Common::String &ntext, TextFont *monitorFont, bool isInteractive, Common::Rect textRect) { Common::String startFileName = _monitorTextFilename; const CloseData *startClosePtr = _closeDataPtr, *lastClosePtr[10]; uint16 depth = 0; Common::String text = ntext; lastClosePtr[0] = _closeDataPtr; while (1) { if (isInteractive) { if (!_closeDataPtr) _closeDataPtr = startClosePtr; Common::String filename; if (_closeDataPtr == startClosePtr) filename = startFileName; else filename = _closeDataPtr->_graphicName; if (filename != _monitorTextFilename) { _monitorPage = 0; _monitorTextFilename = filename; text = _resource->getText(_monitorTextFilename); _graphics->fade(false); drawMonText(text.c_str(), monitorFont, textRect, isInteractive); _graphics->fade(true); } } IntuiMessage *msg = _event->getMsg(); if (shouldQuit()) { _quitLab = true; return; } updateEvents(); _graphics->screenUpdate(); _system->delayMillis(10); if (!msg) continue; MessageClass msgClass = msg->_msgClass; if ((msgClass == kMessageRightClick) || ((msgClass == kMessageRawKey) && (msg->_code == Common::KEYCODE_ESCAPE))) return; if (msgClass == kMessageLeftClick) { int16 mouseX = msg->_mouse.x; int16 mouseY = msg->_mouse.y; // Check if mouse was in button bar if ((mouseY >= _utils->vgaScaleY(171)) && (mouseY <= _utils->vgaScaleY(200))) { if (mouseX <= _utils->vgaScaleX(31)) { // Exit button return; } if (mouseX <= _utils->vgaScaleX(59)) { // Back button if (isInteractive) { _monitorPage = 0; if (depth) { depth--; _closeDataPtr = lastClosePtr[depth]; } } else if (_monitorPage > 0) { _monitorPage = 0; drawMonText(text.c_str(), monitorFont, textRect, isInteractive); } } else if (mouseX < _utils->vgaScaleX(259)) { // empty region; ignore } else if (mouseX <= _utils->vgaScaleX(289)) { // Page down button if (!_lastPage) { _monitorPage += 1; drawMonText(text.c_str(), monitorFont, textRect, isInteractive); } } else if (_monitorPage >= 1) { // Page up button _monitorPage -= 1; drawMonText(text.c_str(), monitorFont, textRect, isInteractive); } } else if (isInteractive) { const CloseData *tmpClosePtr = _closeDataPtr; mouseY = 64 + (mouseY / _monitorButtonHeight) * 42; mouseX = 101; setCurrentClose(Common::Point(mouseX, mouseY), &_closeDataPtr, false); if (tmpClosePtr != _closeDataPtr) { lastClosePtr[depth] = tmpClosePtr; depth++; } } } } // while }
void BArchive::openArchive(const Common::String &path) { byte buf[4]; byte *footer; uint32 footerOffset, footerSize; // Close previously opened archive (if any) closeArchive(); debugCN(2, kDraciArchiverDebugLevel, "Loading archive %s: ", path.c_str()); _f.open(path); if (_f.isOpen()) { debugC(2, kDraciArchiverDebugLevel, "Success"); } else { debugC(2, kDraciArchiverDebugLevel, "Error"); return; } // Save path for reading in files later on _path = path; // Read archive header debugCN(2, kDraciArchiverDebugLevel, "Checking for BAR magic number: "); _f.read(buf, 4); if (memcmp(buf, _magicNumber, 4) == 0) { debugC(2, kDraciArchiverDebugLevel, "Success"); // Indicate this archive is a BAR _isDFW = false; } else { debugC(2, kDraciArchiverDebugLevel, "Not a BAR archive"); debugCN(2, kDraciArchiverDebugLevel, "Retrying as DFW: "); _f.close(); // Try to open as DFW openDFW(_path); return; } _fileCount = _f.readUint16LE(); footerOffset = _f.readUint32LE(); footerSize = _f.size() - footerOffset; debugC(2, kDraciArchiverDebugLevel, "Archive info: %d files, %d data bytes", _fileCount, footerOffset - _archiveHeaderSize); // Read in footer footer = new byte[footerSize]; _f.seek(footerOffset); _f.read(footer, footerSize); Common::MemoryReadStream reader(footer, footerSize); // Read in file headers, but do not read the actual data yet // The data will be read on demand to save memory _files = new BAFile[_fileCount]; for (uint i = 0; i < _fileCount; i++) { uint32 fileOffset; fileOffset = reader.readUint32LE(); _f.seek(fileOffset); // Seek to next file in archive _files[i]._compLength = _f.readUint16LE(); // Compressed size // should be the same as uncompressed _files[i]._length = _f.readUint16LE(); // Original size _files[i]._offset = fileOffset; // Offset of file from start assert(_f.readByte() == 0 && "Compression type flag is non-zero (file is compressed)"); _files[i]._crc = _f.readByte(); // CRC checksum of the file _files[i]._data = NULL; // File data will be read in on demand _files[i]._stopper = 0; // Dummy value; not used in BAR files, needed in DFW } // Last footer item should be equal to footerOffset assert(reader.readUint32LE() == footerOffset && "Footer offset mismatch"); // Indicate that the archive has been successfully opened _opened = true; delete[] footer; }