void Music::getSongNames(Common::StringArray &songs) { songs.clear(); if (IS_SERRATED_SCALPEL) { if (IS_3DO) { Common::FSDirectory gameDirectory(ConfMan.get("path")); Common::FSDirectory *musicDirectory = gameDirectory.getSubDirectory("music"); Common::ArchiveMemberList files; musicDirectory->listMatchingMembers(files, "*_mw22.aifc"); for (Common::ArchiveMemberList::iterator i = files.begin(); i != files.end(); ++i) { Common::String name = (*i)->getName(); name.erase(name.size() - 10); songs.push_back(name); } } else { for (int i = 0; i < ARRAYSIZE(SONG_NAMES); i++) { songs.push_back(SONG_NAMES[i]); } } } else { Common::StringArray fileList; _vm->_res->getResourceNames("music.lib", fileList); for (Common::StringArray::iterator i = fileList.begin(); i != fileList.end(); ++i) { if ((*i).matchString("*.XMI", true)) { (*i).erase((*i).size() - 4); songs.push_back(*i); } } } Common::sort(songs.begin(), songs.end()); }
Common::StringArray Ps2SaveFileManager::listSavefiles(const Common::String &pattern) { Common::FSNode savePath(ConfMan.get("savepath")); // TODO: is this fast? Common::String _dir; Common::String search; bool _mc = (_getDev(savePath) == MC_DEV); // (strncmp(savePath.getPath().c_str(), "mc0:", 4) == 0); char *game=0, path[32], temp[32]; if (!savePath.exists() || !savePath.isDirectory()) return Common::StringArray(); printf("listSavefiles = %s\n", pattern.c_str()); if (_mc) { strcpy(temp, pattern.c_str()); // mcSplit(temp, game, ext); game = strdup(strtok(temp, ".")); sprintf(path, "mc0:ScummVM/%s", game); // per game path mcCheck(path); sprintf(path, "mc0:ScummVM/%s/", game); _dir = Common::String(path); search = Common::String("*.sav"); } else { _dir = Common::String(savePath.getPath()); search = pattern; } Common::FSDirectory dir(_dir); Common::ArchiveMemberList savefiles; Common::StringArray results; printf("dir = %s --- reg = %s\n", _dir.c_str(), search.c_str()); if (dir.listMatchingMembers(savefiles, search) > 0) { for (Common::ArchiveMemberList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) { if (_mc) { // convert them back in ScummVM names strncpy(temp, (*file)->getName().c_str(), 3); temp[3] = '\0'; sprintf(path, "%s.%s", game, temp); results.push_back(path); printf(" --> found = %s -> %s\n", (*file)->getName().c_str(), path); } else { results.push_back((*file)->getName()); printf(" --> found = %s\n", (*file)->getName().c_str()); } } } free(game); return results; }
void Resources::getResourceNames(const Common::String &libraryFile, Common::StringArray &names) { addToCache(libraryFile); LibraryIndex &libIndex = _indexes[libraryFile]; for (LibraryIndex::iterator i = libIndex.begin(); i != libIndex.end(); ++i) { names.push_back(i->_key); } }
Common::StringArray GBAMPSaveFileManager::listSavefiles(const Common::String &pattern) { enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 }; char name[256]; { char dir[128]; strcpy(dir, getSavePath().c_str()); char *realName = dir; if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) { realName += 4; } // consolePrintf("Real cwd:%d\n", realName); char *p = realName; while (*p) { if (*p == '\\') *p = '/'; p++; } // consolePrintf("Real cwd:%d\n", realName); FAT_chdir(realName); } // consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(), pattern); int fileType = FAT_FindFirstFileLFN(name); Common::StringArray list; do { if (fileType == TYPE_FILE) { FAT_GetLongFilename(name); for (int r = 0; name[r] != 0; r++) { name[r] = tolower(name[r]); } if (Common::matchString(name, pattern.c_str())) { list.push_back(name); } } } while ((fileType = FAT_FindNextFileLFN(name))); FAT_chdir("/"); return list; }
Common::StringArray *World::readMenu(Common::SeekableReadStream *res) { res->skip(10); int enableFlags = res->readUint32BE(); Common::String menuName = readPascalString(res); Common::String menuItem = readPascalString(res); int menuItemNumber = 1; Common::String menu; byte itemData[4]; while (!menuItem.empty()) { if (!menu.empty()) { menu += ';'; } if ((enableFlags & (1 << menuItemNumber)) == 0) { menu += '('; } menu += menuItem; res->read(itemData, 4); static const char styles[] = {'B', 'I', 'U', 'O', 'S', 'C', 'E', 0}; for (int i = 0; styles[i] != 0; i++) { if ((itemData[3] & (1 << i)) != 0) { menu += '<'; menu += styles[i]; } } if (itemData[1] != 0) { menu += '/'; menu += (char)itemData[1]; } menuItem = readPascalString(res); menuItemNumber++; } Common::StringArray *result = new Common::StringArray; result->push_back(menuName); result->push_back(menu); debug(4, "menuName: %s", menuName.c_str()); debug(4, "menu: %s", menu.c_str()); return result; }
void Console::printWordMap(const WordMap &wordMap) { Common::StringArray words; WordMap::const_iterator verb; for (verb = wordMap.begin(); verb != wordMap.end(); ++verb) words.push_back(Common::String::format("%s: %3d", toAscii(verb->_key).c_str(), wordMap[verb->_key])); Common::sort(words.begin(), words.end()); debugPrintColumns(words); }
Common::StringArray EventRecorder::listSaveFiles(const Common::String &pattern) { if (_recordMode == kRecorderPlayback) { Common::StringArray result; for (Common::HashMap<Common::String, Common::PlaybackFile::SaveFileBuffer>::iterator i = _playbackFile->getHeader().saveFiles.begin(); i != _playbackFile->getHeader().saveFiles.end(); ++i) { if (i->_key.matchString(pattern, false, true)) { result.push_back(i->_key); } } return result; } else { return _realSaveManager->listSavefiles(pattern); } }
MusicDevices WindowsMusicPlugin::getDevices() const { MusicDevices devices; int numDevs = midiOutGetNumDevs(); MIDIOUTCAPS tmp; Common::StringArray deviceNames; for (int i = 0; i < numDevs; i++) { if (midiOutGetDevCaps(i, &tmp, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR) break; deviceNames.push_back(tmp.szPname); } // Check for non-unique device names. This may happen if someone has devices with identical // names (e. g. more than one USB device of the exact same hardware type). It seems that this // does happen in reality sometimes. We generate index numbers for these devices. // This is not an ideal solution, since this index could change whenever another USB // device gets plugged in or removed, switched off or just plugged into a different port. // Unfortunately midiOutGetDevCaps() does not generate any other unique information // that could be used. Our index numbers which match the device order should at least be // a little more stable than just using the midiOutGetDevCaps() device ID, since a missing // device (e.g. switched off) should actually not be harmful to our indices (as it would be // when using the device IDs). The cases where users have devices with identical names should // be rare enough anyway. Common::Array<int> nonUniqueIndex; for (int i = 0; i < numDevs; i++) { int match = -1; for (int ii = 0; ii < i; ii++) { if (deviceNames[i] == deviceNames[ii]) { if (nonUniqueIndex[ii] == -1) nonUniqueIndex[ii] = 0; if (++match == 0) ++match; } } nonUniqueIndex.push_back(match); } // We now add the index number to the non-unique device names to make them unique. for (int i = 0; i < numDevs; i++) { if (nonUniqueIndex[i] != -1) deviceNames[i] = Common::String::format("%s - #%.02d", deviceNames[i].c_str(), nonUniqueIndex[i]); } for (Common::StringArray::iterator i = deviceNames.begin(); i != deviceNames.end(); ++i) // There is no way to detect the "MusicType" so I just set it to MT_GM // The user will have to manually select his MT32 type device and his GM type device. devices.push_back(MusicDevice(this, *i, MT_GM)); return devices; }
bool Console::Cmd_Vars(int argc, const char **argv) { if (argc != 1) { debugPrintf("Usage: %s\n", argv[0]); return true; } Common::StringArray vars; for (uint i = 0; i < _engine->_state.vars.size(); ++i) vars.push_back(Common::String::format("%3d: %3d", i, _engine->_state.vars[i])); debugPrintf("Variables:\n"); debugPrintColumns(vars); return true; }
Common::StringArray Game::getMessage(uint32 id) { File f("*MESSAGES.DAT"); int count = f.readUint16LE(); for (int idx = 0; idx < count; ++idx) { uint32 itemId = f.readUint32LE(); uint32 offset = f.readUint32LE(); uint16 size = f.readUint16LE(); if (itemId == id) { // Get the source buffer size uint16 sizeIn; if (idx == (count - 1)) { sizeIn = f.size() - offset; } else { f.skip(4); uint32 nextOffset = f.readUint32LE(); sizeIn = nextOffset - offset; } // Get the compressed data f.seek(offset); byte *bufferIn = new byte[sizeIn]; f.read(bufferIn, sizeIn); // Decompress it char *bufferOut = new char[size]; FabDecompressor fab; fab.decompress(bufferIn, sizeIn, (byte *)bufferOut, size); // Form the output string list Common::StringArray result; const char *p = bufferOut; while (p < (bufferOut + size)) { result.push_back(p); p += strlen(p) + 1; } delete[] bufferIn; delete[] bufferOut; return result; } } error("Invalid message Id specified"); }
Common::StringArray PAKSaveManager::listSavefiles(const Common::String &pattern) { PAKDIR *dirp = pakfs_opendir(); pakfs_dirent *dp; Common::StringArray list; Common::String *fname; while ((dp = pakfs_readdir(dirp)) != NULL) { fname = new Common::String(dp->entryname); if (fname->matchString(pattern, false, false)) list.push_back(dp->entryname); delete fname; free(dp); } pakfs_closedir(dirp); return list; }
Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) { // Assure the savefile name cache is up-to-date. assureCached(getSavePath()); if (getError().getCode() != Common::kNoError) return Common::StringArray(); Common::HashMap<Common::String, bool> locked; for (Common::StringArray::const_iterator i = _lockedFiles.begin(), end = _lockedFiles.end(); i != end; ++i) { locked[*i] = true; } Common::StringArray results; for (SaveFileCache::const_iterator file = _saveFileCache.begin(), end = _saveFileCache.end(); file != end; ++file) { if (!locked.contains(file->_key) && file->_key.matchString(pattern, true)) { results.push_back(file->_key); } } return results; }
CMusicSong::CMusicSong(int index) { // Read in the list of song strings Common::SeekableReadStream *res = g_vm->_filesManager->getResource("MUSIC/PARSER"); Common::StringArray parserStrings; while (res->pos() < res->size()) parserStrings.push_back(readStringFromStream(res)); delete res; // Set up a new song parser with the desired string CSongParser parser(parserStrings[index].c_str()); // Count how many encoded values there are CValuePair r; int count = 0; while (parser.parse(r)) ++count; assert(count > 0); // Read in the values to the array _data.resize(count); parser.reset(); for (int idx = 0; idx < count; ++idx) parser.parse(_data[idx]); // Figure out the range of values in the array _minVal = 0x7FFFFFFF; int maxVal = -0x7FFFFFFF; for (int idx = 0; idx < count; ++idx) { CValuePair &vp = _data[idx]; if (vp._data != 0x7FFFFFFF) { if (vp._data < _minVal) _minVal = vp._data; if (vp._data > maxVal) maxVal = vp._data; } } _range = maxVal - _minVal; }
void Lingo::runTests() { Common::File inFile; Common::ArchiveMemberList fsList; SearchMan.listMatchingMembers(fsList, "*.lingo"); Common::StringArray fileList; int counter = 1; for (Common::ArchiveMemberList::iterator it = fsList.begin(); it != fsList.end(); ++it) fileList.push_back((*it)->getName()); Common::sort(fileList.begin(), fileList.end()); for (uint i = 0; i < fileList.size(); i++) { Common::SeekableReadStream *const stream = SearchMan.createReadStreamForMember(fileList[i]); if (stream) { uint size = stream->size(); char *script = (char *)calloc(size + 1, 1); stream->read(script, size); debugC(2, kDebugLingoCompile, "Compiling file %s of size %d, id: %d", fileList[i].c_str(), size, counter); _hadError = false; addCode(script, kMovieScript, counter); if (!_hadError) executeScript(kMovieScript, counter); else debugC(2, kDebugLingoCompile, "Skipping execution"); free(script); counter++; } inFile.close(); } }
Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) { Common::String savePathName = getSavePath(); checkPath(Common::FSNode(savePathName)); if (getError().getCode() != Common::kNoError) return Common::StringArray(); // recreate FSNode since checkPath may have changed/created the directory Common::FSNode savePath(savePathName); Common::FSDirectory dir(savePath); Common::ArchiveMemberList savefiles; Common::StringArray results; Common::String search(pattern); if (dir.listMatchingMembers(savefiles, search) > 0) { for (Common::ArchiveMemberList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) { results.push_back((*file)->getName()); } } return results; }
Common::String WidgetBase::splitLines(const Common::String &str, Common::StringArray &lines, int maxWidth, uint maxLines) { Talk &talk = *_vm->_talk; const char *strP = str.c_str(); // Loop counting up lines lines.clear(); do { int width = 0; const char *spaceP = nullptr; const char *lineStartP = strP; // Find how many characters will fit on the next line while (width < maxWidth && *strP && ((byte)*strP < talk._opcodes[OP_SWITCH_SPEAKER] || (byte)*strP == talk._opcodes[OP_NULL])) { width += _surface.charWidth(*strP); // Keep track of the last space if (*strP == ' ') spaceP = strP; ++strP; } // If the line was too wide to fit on a single line, go back to the last space // if there was one, or otherwise simply break the line at this point if (width >= maxWidth && spaceP != nullptr) strP = spaceP; // Add the line to the output array lines.push_back(Common::String(lineStartP, strP)); // Move the string ahead to the next line if (*strP == ' ' || *strP == 13) ++strP; } while (*strP && (lines.size() < maxLines) && ((byte)*strP < talk._opcodes[OP_SWITCH_SPEAKER] || (byte)*strP == talk._opcodes[OP_NULL])); // Return any remaining text left over return *strP ? Common::String(strP) : Common::String(); }
/* bind accept the following input formats: 1 - [S].slide.[L]{.[C]} 2 - [L]{.[C]} where: [S] is the slide to be shown [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1) [C] is the character to be selected, and is optional The routine tells one form from the other by searching for the '.slide.' NOTE: there exists one script in which [L] is not used in the case 1, but its use is commented out, and would definitely crash the current implementation. */ void LocationName::bind(const char *s) { free(_buf); _buf = strdup(s); _hasSlide = false; _hasCharacter = false; Common::StringArray list; char *tok = strtok(_buf, "."); while (tok) { list.push_back(tok); tok = strtok(NULL, "."); } if (list.size() < 1 || list.size() > 4) error("changeLocation: ill-formed location name '%s'", s); if (list.size() > 1) { if (list[1] == "slide") { _hasSlide = true; _slide = list[0]; list.remove_at(0); // removes slide name list.remove_at(0); // removes 'slide' } if (list.size() == 2) { _hasCharacter = true; _character = list[1]; } } _location = list[0]; strcpy(_buf, s); // kept as reference }
bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { if (argc < 4) { DebugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n"); return true; } uint16 oldStack = _vm->getCurStack(); byte newStack = 0; for (byte i = 1; i <= tspit + 1; i++) if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) { newStack = i; break; } if (!newStack) { DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } newStack--; _vm->changeToStack(newStack); // Load in Variable Names Common::SeekableReadStream *nameStream = _vm->getResource(ID_NAME, VariableNames); Common::StringArray varNames; uint16 namesCount = nameStream->readUint16BE(); uint16 *stringOffsets = new uint16[namesCount]; for (uint16 i = 0; i < namesCount; i++) stringOffsets[i] = nameStream->readUint16BE(); nameStream->seek(namesCount * 2, SEEK_CUR); int32 curNamesPos = nameStream->pos(); for (uint32 i = 0; i < namesCount; i++) { nameStream->seek(curNamesPos + stringOffsets[i]); Common::String name; for (char c = nameStream->readByte(); c; c = nameStream->readByte()) name += c; varNames.push_back(name); } delete nameStream; // Load in External Command Names nameStream = _vm->getResource(ID_NAME, ExternalCommandNames); Common::StringArray xNames; namesCount = nameStream->readUint16BE(); stringOffsets = new uint16[namesCount]; for (uint16 i = 0; i < namesCount; i++) stringOffsets[i] = nameStream->readUint16BE(); nameStream->seek(namesCount * 2, SEEK_CUR); curNamesPos = nameStream->pos(); for (uint32 i = 0; i < namesCount; i++) { nameStream->seek(curNamesPos + stringOffsets[i]); Common::String name; for (char c = nameStream->readByte(); c; c = nameStream->readByte()) name += c; xNames.push_back(name); } delete nameStream; // Get CARD/HSPT data and dump their scripts if (!scumm_stricmp(argv[2], "CARD")) { // Use debugN to print these because the scripts can get very large and would // really be useless if the the text console is not used. A DumpFile could also // theoretically be used, but I (clone2727) typically use this dynamically and // don't want countless files laying around without game context. If one would // want a file of a script they could just redirect stdout to a file or use // deriven. debugN("\n\nDumping scripts for %s\'s card %d!\n", argv[1], (uint16)atoi(argv[3])); debugN("==================================\n\n"); Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3])); cardStream->seek(4); RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false); for (uint32 i = 0; i < scriptList.size(); i++) { scriptList[i]->dumpScript(varNames, xNames, 0); delete scriptList[i]; } delete cardStream; } else if (!scumm_stricmp(argv[2], "HSPT")) { // See above for why this is printed via debugN debugN("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3])); debugN("===========================================\n\n"); Common::SeekableReadStream *hsptStream = _vm->getResource(MKTAG('H','S','P','T'), (uint16)atoi(argv[3])); uint16 hotspotCount = hsptStream->readUint16BE(); for (uint16 i = 0; i < hotspotCount; i++) { debugN("Hotspot %d:\n", i); hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false); for (uint32 j = 0; j < scriptList.size(); j++) { scriptList[j]->dumpScript(varNames, xNames, 1); delete scriptList[j]; } } delete hsptStream; } else { DebugPrintf("%s doesn't have any scripts!\n", argv[2]); } // See above for why this is printed via debugN debugN("\n\n"); _vm->changeToStack(oldStack); DebugPrintf("Script dump complete.\n"); return true; }