diff options
| -rw-r--r-- | engines/sci/engine/kernel.h | 1 | ||||
| -rw-r--r-- | engines/sci/engine/kernel_tables.h | 6 | ||||
| -rw-r--r-- | engines/sci/engine/kfile.cpp | 70 | 
3 files changed, 49 insertions, 28 deletions
| diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index f37d878d57..e1ec5c0dde 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -488,6 +488,7 @@ reg_t kSaveSave32(EngineState *s, int argc, reg_t *argv);  reg_t kSaveRestore32(EngineState *s, int argc, reg_t *argv);  reg_t kSaveList32(EngineState *s, int argc, reg_t *argv);  reg_t kSaveCheck32(EngineState *s, int argc, reg_t *argv); +reg_t kSaveMakeFileName32(EngineState *s, int argc, reg_t *argv);  reg_t kSetHotRectangles(EngineState *s, int argc, reg_t *argv);  reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index d234edb67b..7244262b9d 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -362,7 +362,7 @@ static const SciKernelMapSubEntry kSave_subops[] = {  	// Subop 4 hasn't been encountered yet  	{ SIG_SCI32,           5, MAP_CALL(SaveList32),                "rrr",                  NULL },  	{ SIG_SCI32,           6, MAP_CALL(MakeSaveCatName),           "rr",                   NULL }, -	{ SIG_SCI32,           7, MAP_CALL(MakeSaveFileName),          "rri",                  NULL }, +	{ SIG_SCI32,           7, MAP_CALL(SaveMakeFileName32),        "rri",                  NULL },  	{ SIG_SCI32,           8, MAP_EMPTY(GameIsRestarting),         ".*",                   NULL },  	SCI_SUBOPENTRY_TERMINATOR  }; @@ -686,7 +686,7 @@ static SciKernelMapEntry s_kernelMap[] = {  	{ MAP_CALL(GetMessage),        SIG_EVERYWHERE,           "iiir",                  NULL,            NULL },  	{ MAP_CALL(GetPort),           SIG_EVERYWHERE,           "",                      NULL,            NULL },  #ifdef ENABLE_SCI32 -	{ MAP_CALL(GetSaveDir),        SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "",              NULL,            NULL }, +	{ MAP_CALL(GetSaveDir),        SIG_UNTIL_SCI21EARLY, SIGFOR_ALL, "(r)",           NULL,            NULL },  #endif  	{ MAP_CALL(GetSaveDir),        SIG_SCI16, SIGFOR_ALL,    "",                      NULL,            NULL },  #ifdef ENABLE_SCI32 @@ -871,7 +871,7 @@ static SciKernelMapEntry s_kernelMap[] = {  	{ MAP_CALL(ObjectIntersect),   SIG_EVERYWHERE,           "oo",                    NULL,            NULL },  	{ MAP_CALL(EditText),          SIG_EVERYWHERE,           "o",                     NULL,            NULL },  	{ MAP_CALL(MakeSaveCatName),   SIG_EVERYWHERE,           "rr",                    NULL,            NULL }, -	{ MAP_CALL(MakeSaveFileName),  SIG_EVERYWHERE,           "rri",                   NULL,            NULL }, +	{ "MakeSaveFileName", kSaveMakeFileName32, SIG_UNTIL_SCI21MID, SIGFOR_ALL, "rri", NULL,            NULL },  	{ MAP_CALL(SetScroll),         SIG_EVERYWHERE,           "oiiii(i)(i)",           NULL,            NULL },  	{ MAP_CALL(PalCycle),          SIG_EVERYWHERE,           "(.*)",                  kPalCycle_subops, NULL }, diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 00138ae224..797cd5d570 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -51,6 +51,7 @@ extern FileHandle *getFileFromHandle(EngineState *s, uint handle);  extern int fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle);  extern void listSavegames(Common::Array<SavegameDesc> &saves);  extern int findSavegame(Common::Array<SavegameDesc> &saves, int16 savegameId); +extern bool fillSavegameDesc(const Common::String &filename, SavegameDesc *desc);  /**   * Writes the cwd to the supplied address and returns the address in acc. @@ -270,7 +271,10 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {  		if (name == "autosave.cat") {  			exists = !saveFileMan->listSavefiles(g_sci->getSavegameName(0)).empty();  		} else { -			exists = !saveFileMan->listSavefiles(g_sci->getSavegamePattern()).empty(); +			// There will always be one save game in Torin, the "new game" game, +			// which should be ignored when deciding if there are any save games +			// to open +			exists = saveFileMan->listSavefiles(g_sci->getSavegamePattern()).size() > 1;  		}  		if (exists) { @@ -1049,9 +1053,36 @@ reg_t kSaveSave32(EngineState *s, int argc, reg_t *argv) {  			// Autosave slot 1 is a "new game" save  			saveNo = kNewGameId;  		} -	} +	} else if (saveNo == 0) { +		// SSCI save games normally start from save number 0, but this is +		// reserved for the autosave game in ScummVM. So, any time a game tries +		// to save to slot 0 (and it isn't an autosave), it should instead go to +		// the next highest free ID +		Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); +		Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); +		Common::sort(saveNames.begin(), saveNames.end()); +		if (saveNames.size()) { +			int lastId = 0; +			for (int i = 0; i < (int)saveNames.size(); ++i) { +				const int id = strtol(saveNames[i].end() - 3, NULL, 10); +				if (id == 0) { +					continue; +				} + +				if (id != lastId + 1) { +					saveNo = lastId + 1; +					break; +				} -	assert(gameName == "Autosave" || gameName == "Autosv" || saveNo > 0); +				++lastId; +			} +		} + +		// There was no gap, so this save goes to a brand new slot +		if (saveNo == 0) { +			saveNo = saveNames.size() + 1; +		} +	}  	Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();  	const Common::String filename = g_sci->getSavegameName(saveNo); @@ -1118,12 +1149,14 @@ reg_t kSaveCheck32(EngineState *s, int argc, reg_t *argv) {  	Common::Array<SavegameDesc> saves;  	listSavegames(saves); -	const int16 saveIndex = findSavegame(saves, saveNo); -	if (saveIndex == -1) { -		return NULL_REG; +	if ((gameName == "Autosave" || gameName == "Autosv") && saveNo == 1) { +		saveNo = kNewGameId;  	} -	const SavegameDesc &save = saves[saveIndex]; +	SavegameDesc save; +	if (!fillSavegameDesc(g_sci->getSavegameName(saveNo), &save)) { +		return NULL_REG; +	}  	if (save.version < MINIMUM_SAVEGAME_VERSION ||  		save.version > CURRENT_SAVEGAME_VERSION || @@ -1167,24 +1200,11 @@ reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv) {  	return argv[0];  } -reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) { -	// Creates a savegame name from a slot number. Used when deleting saved games. -	// Param 0: the output buffer (same as in kMakeSaveCatName) -	// Param 1: a string with game parameters, ignored -	// Param 2: the selected slot - -	SciArray *resultString = s->_segMan->lookupArray(argv[0]); -	uint16 virtualId = argv[2].toUint16(); -	if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) -		error("kMakeSaveFileName: invalid savegame ID specified"); -	uint saveSlot = virtualId - SAVEGAMEID_OFFICIALRANGE_START; - -	Common::Array<SavegameDesc> saves; -	listSavegames(saves); - -	Common::String filename = g_sci->getSavegameName(saveSlot); -	resultString->fromString(filename); - +reg_t kSaveMakeFileName32(EngineState *s, int argc, reg_t *argv) { +	SciArray &outFileName = *s->_segMan->lookupArray(argv[0]); +	// argv[1] is the game name, which is not used by ScummVM +	int16 saveNo = argv[2].toSint16(); +	outFileName.fromString(g_sci->getSavegameName(saveNo));  	return argv[0];  } | 
