Common::StringArray Kernel::checkStaticSelectorNames() { Common::StringArray names; const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0; #ifdef ENABLE_SCI32 const int count = (getSciVersion() <= SCI_VERSION_1_1) ? ARRAYSIZE(sci0Selectors) + offset : ARRAYSIZE(sci2Selectors); #else const int count = ARRAYSIZE(sci0Selectors) + offset; #endif int countSci1 = ARRAYSIZE(sci1Selectors); int countSci11 = ARRAYSIZE(sci11Selectors); // Resize the list of selector names and fill in the SCI 0 names. names.resize(count); if (getSciVersion() <= SCI_VERSION_1_LATE) { // Fill selectors 0 - 2 for SCI0 - SCI1 late names[0] = "species"; names[1] = "superClass"; names[2] = "-info-"; } if (getSciVersion() <= SCI_VERSION_1_1) { // SCI0 - SCI11 for (int i = offset; i < count; i++) names[i] = sci0Selectors[i - offset]; if (getSciVersion() > SCI_VERSION_01) { // Several new selectors were added in SCI 1 and later. names.resize(count + countSci1); for (int i = count; i < count + countSci1; i++) names[i] = sci1Selectors[i - count]; } if (getSciVersion() >= SCI_VERSION_1_1) { // Several new selectors were added in SCI 1.1 names.resize(count + countSci1 + countSci11); for (int i = count + countSci1; i < count + countSci1 + countSci11; i++) names[i] = sci11Selectors[i - count - countSci1]; } #ifdef ENABLE_SCI32 } else { // SCI2+ for (int i = 0; i < count; i++) names[i] = sci2Selectors[i]; #endif } findSpecificSelectors(names); for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) { if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) { const uint32 slot = selectorRemap->slot; if (slot >= names.size()) names.resize(slot + 1); names[slot] = selectorRemap->name; } } return names; }
SaveStateList SkyMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); SaveStateList saveList; // Load the descriptions Common::StringArray savenames; savenames.resize(MAX_SAVE_GAMES+1); Common::InSaveFile *inf; inf = saveFileMan->openForLoading("SKY-VM.SAV"); if (inf != NULL) { char *tmpBuf = new char[MAX_SAVE_GAMES * MAX_TEXT_LEN]; char *tmpPtr = tmpBuf; inf->read(tmpBuf, MAX_SAVE_GAMES * MAX_TEXT_LEN); for (int i = 0; i < MAX_SAVE_GAMES; ++i) { savenames[i] = tmpPtr; tmpPtr += savenames[i].size() + 1; } delete inf; delete[] tmpBuf; } // Find all saves Common::StringArray filenames; filenames = saveFileMan->listSavefiles("SKY-VM.???"); sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) // Slot 0 is the autosave, if it exists. // TODO: Check for the existence of the autosave -- but this require us // to know which SKY variant we are looking at. saveList.insert_at(0, SaveStateDescriptor(0, "*AUTOSAVE*")); // Prepare the list of savestates by looping over all matching savefiles for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { // Extract the extension Common::String ext = file->c_str() + file->size() - 3; ext.toUppercase(); if (Common::isDigit(ext[0]) && Common::isDigit(ext[1]) && Common::isDigit(ext[2])) { int slotNum = atoi(ext.c_str()); Common::InSaveFile *in = saveFileMan->openForLoading(*file); if (in) { saveList.push_back(SaveStateDescriptor(slotNum+1, savenames[slotNum])); delete in; } } } return saveList; }
void SkyMetaEngine::removeSaveState(const char *target, int slot) const { if (slot == 0) // do not delete the auto save return; Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); char fName[20]; sprintf(fName,"SKY-VM.%03d", slot - 1); saveFileMan->removeSavefile(fName); // Load current save game descriptions Common::StringArray savenames; savenames.resize(MAX_SAVE_GAMES+1); Common::InSaveFile *inf; inf = saveFileMan->openForLoading("SKY-VM.SAV"); if (inf != NULL) { char *tmpBuf = new char[MAX_SAVE_GAMES * MAX_TEXT_LEN]; char *tmpPtr = tmpBuf; inf->read(tmpBuf, MAX_SAVE_GAMES * MAX_TEXT_LEN); for (int i = 0; i < MAX_SAVE_GAMES; ++i) { savenames[i] = tmpPtr; tmpPtr += savenames[i].size() + 1; } delete inf; delete[] tmpBuf; } // Update the save game description at the given slot savenames[slot - 1] = ""; // Save the updated descriptions Common::OutSaveFile *outf; outf = saveFileMan->openForSaving("SKY-VM.SAV"); bool ioFailed = true; if (outf) { for (uint16 cnt = 0; cnt < MAX_SAVE_GAMES; cnt++) { outf->write(savenames[cnt].c_str(), savenames[cnt].size() + 1); } outf->finalize(); if (!outf->err()) ioFailed = false; delete outf; } if (ioFailed) warning("Unable to store Savegame names to file SKY-VM.SAV. (%s)", saveFileMan->popErrorDesc().c_str()); }
Common::Error SkyEngine::saveGameState(int slot, const Common::String &desc) { if (slot == 0) return Common::kWritePermissionDenied; // we can't overwrite the auto save // Set the save slot and save the game _skyControl->_selectedGame = slot - 1; if (_skyControl->saveGameToFile(false) != GAME_SAVED) return Common::kWritePermissionDenied; // Load current save game descriptions Common::StringArray saveGameTexts; saveGameTexts.resize(MAX_SAVE_GAMES+1); _skyControl->loadDescriptions(saveGameTexts); // Update the save game description at the given slot saveGameTexts[slot - 1] = desc; // Save the updated descriptions _skyControl->saveDescriptions(saveGameTexts); return Common::kNoError; }
void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) { // Now, we need to find out selectors which keep changing place... // We do that by dissecting game objects, and looking for selectors at // specified locations. // We need to initialize script 0 here, to make sure that it's always // located at segment 1. _segMan->instantiateScript(0); // The Actor class contains the init, xLast and yLast selectors, which // we reference directly. It's always in script 998, so we need to // explicitly load it here. if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) { uint16 actorScript = 998; #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { actorScript += 64000; } #endif if (_resMan->testResource(ResourceId(kResourceTypeScript, actorScript))) { _segMan->instantiateScript(actorScript); const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor")); if (actorClass) { // Find the xLast and yLast selectors, used in kDoBresen int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0; #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { offset += 12; } #endif // xLast and yLast always come between illegalBits and xStep int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset); // illegalBits int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset); // xStep if (xStepSelectorPos - illegalBitsSelectorPos != 3) { error("illegalBits and xStep selectors aren't found in " "known locations. illegalBits = %d, xStep = %d", illegalBitsSelectorPos, xStepSelectorPos); } int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1); int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2); if (selectorNames.size() < (uint32)yLastSelectorPos + 1) selectorNames.resize((uint32)yLastSelectorPos + 1); selectorNames[xLastSelectorPos] = "xLast"; selectorNames[yLastSelectorPos] = "yLast"; } _segMan->uninstantiateScript(actorScript); } } // Find selectors from specific classes for (int i = 0; i < ARRAYSIZE(classReferences); i++) { if (!_resMan->testResource(ResourceId(kResourceTypeScript, classReferences[i].script))) continue; _segMan->instantiateScript(classReferences[i].script); const Object *targetClass = _segMan->getObject(_segMan->findObjectByName(classReferences[i].className)); int targetSelectorPos = 0; uint selectorOffset = classReferences[i].selectorOffset; if (targetClass) { if (classReferences[i].selectorType == kSelectorMethod) { if (targetClass->getMethodCount() < selectorOffset + 1) error("The %s class has less than %d methods (%d)", classReferences[i].className, selectorOffset + 1, targetClass->getMethodCount()); targetSelectorPos = targetClass->getFuncSelector(selectorOffset); } else { // Add the global selectors to the selector ID selectorOffset += (getSciVersion() <= SCI_VERSION_1_LATE) ? 3 : 8; if (targetClass->getVarCount() < selectorOffset + 1) error("The %s class has less than %d variables (%d)", classReferences[i].className, selectorOffset + 1, targetClass->getVarCount()); targetSelectorPos = targetClass->getVarSelector(selectorOffset); } if (selectorNames.size() < (uint32)targetSelectorPos + 1) selectorNames.resize((uint32)targetSelectorPos + 1); selectorNames[targetSelectorPos] = classReferences[i].selectorName; } } _segMan->resetSegMan(); }