1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/scummsys.h"
24 
25 #include "base/plugins.h"
26 
27 #include "engines/advancedDetector.h"
28 
29 #include "zvision/zvision.h"
30 #include "zvision/file/save_manager.h"
31 #include "zvision/scripting/script_manager.h"
32 
33 #include "common/translation.h"
34 #include "common/savefile.h"
35 #include "common/str-array.h"
36 #include "common/system.h"
37 
38 namespace ZVision {
39 
40 struct ZVisionGameDescription {
41 	ADGameDescription desc;
42 	ZVisionGameId gameId;
43 };
44 
getGameId() const45 ZVisionGameId ZVision::getGameId() const {
46 	return _gameDescription->gameId;
47 }
getLanguage() const48 Common::Language ZVision::getLanguage() const {
49 	return _gameDescription->desc.language;
50 }
getFeatures() const51 uint32 ZVision::getFeatures() const {
52 	return _gameDescription->desc.flags;
53 }
54 
55 } // End of namespace ZVision
56 
57 #include "zvision/detection_tables.h"
58 
59 class ZVisionMetaEngine : public AdvancedMetaEngine {
60 public:
ZVisionMetaEngine()61 	ZVisionMetaEngine() : AdvancedMetaEngine(ZVision::gameDescriptions, sizeof(ZVision::ZVisionGameDescription), ZVision::zVisionGames, ZVision::optionsList) {
62 		_maxScanDepth = 2;
63 		_directoryGlobs = ZVision::directoryGlobs;
64 		_singleId = "zvision";
65 	}
66 
getName() const67 	virtual const char *getName() const {
68 		return "Z-Vision";
69 	}
70 
getOriginalCopyright() const71 	virtual const char *getOriginalCopyright() const {
72 		return "Z-Vision (C) 1996 Activision";
73 	}
74 
75 	virtual bool hasFeature(MetaEngineFeature f) const;
76 	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
77 	SaveStateList listSaves(const char *target) const;
78 	virtual int getMaximumSaveSlot() const;
79 	void removeSaveState(const char *target, int slot) const;
80 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
81 };
82 
hasFeature(MetaEngineFeature f) const83 bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const {
84 	return
85 		(f == kSupportsListSaves) ||
86 		(f == kSupportsLoadingDuringStartup) ||
87 		(f == kSupportsDeleteSave) ||
88 		(f == kSavesSupportMetaInfo) ||
89 		(f == kSavesSupportThumbnail) ||
90 		(f == kSavesSupportCreationDate) ||
91 		(f == kSavesSupportPlayTime) ||
92 		(f == kSimpleSavesNames);
93 }
94 
hasFeature(EngineFeature f) const95 bool ZVision::ZVision::hasFeature(EngineFeature f) const {
96 	return
97 		(f == kSupportsRTL) ||
98 		(f == kSupportsLoadingDuringRuntime) ||
99 		(f == kSupportsSavingDuringRuntime);
100 }
101 
loadGameState(int slot)102 Common::Error ZVision::ZVision::loadGameState(int slot) {
103 	return _saveManager->loadGame(slot);
104 }
105 
saveGameState(int slot,const Common::String & desc)106 Common::Error ZVision::ZVision::saveGameState(int slot, const Common::String &desc) {
107 	_saveManager->saveGame(slot, desc, false);
108 	return Common::kNoError;
109 }
110 
canLoadGameStateCurrently()111 bool ZVision::ZVision::canLoadGameStateCurrently() {
112 	return !_videoIsPlaying;
113 }
114 
canSaveGameStateCurrently()115 bool ZVision::ZVision::canSaveGameStateCurrently() {
116 	Location currentLocation = _scriptManager->getCurrentLocation();
117 	return !_videoIsPlaying && currentLocation.world != 'g' && !(currentLocation.room == 'j' || currentLocation.room == 'a');
118 }
119 
createInstance(OSystem * syst,Engine ** engine,const ADGameDescription * desc) const120 bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
121 	const ZVision::ZVisionGameDescription *gd = (const ZVision::ZVisionGameDescription *)desc;
122 	if (gd) {
123 		*engine = new ZVision::ZVision(syst, gd);
124 	}
125 	return gd != 0;
126 }
127 
listSaves(const char * target) const128 SaveStateList ZVisionMetaEngine::listSaves(const char *target) const {
129 	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
130 	ZVision::SaveGameHeader header;
131 	Common::String pattern = target;
132 	pattern += ".###";
133 
134 	Common::StringArray filenames;
135 	filenames = saveFileMan->listSavefiles(pattern.c_str());
136 
137 	SaveStateList saveList;
138 	// We only use readSaveGameHeader() here, which doesn't need an engine callback
139 	ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL);
140 
141 	for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
142 		// Obtain the last 3 digits of the filename, since they correspond to the save slot
143 		int slotNum = atoi(file->c_str() + file->size() - 3);
144 
145 		if (slotNum >= 0 && slotNum <= 999) {
146 			Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
147 			if (in) {
148 				if (zvisionSaveMan->readSaveGameHeader(in, header)) {
149 					saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
150 				}
151 				delete in;
152 			}
153 		}
154 	}
155 
156 	delete zvisionSaveMan;
157 
158 	// Sort saves based on slot number.
159 	Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
160 	return saveList;
161 }
162 
getMaximumSaveSlot() const163 int ZVisionMetaEngine::getMaximumSaveSlot() const {
164 	return 999;
165 }
166 
removeSaveState(const char * target,int slot) const167 void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const {
168 	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
169 	saveFileMan->removeSavefile(Common::String::format("%s.%03u", target, slot));
170 }
171 
querySaveMetaInfos(const char * target,int slot) const172 SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
173 	Common::String filename = Common::String::format("%s.%03u", target, slot);
174 	Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
175 
176 	if (in) {
177 		ZVision::SaveGameHeader header;
178 
179 		// We only use readSaveGameHeader() here, which doesn't need an engine callback
180 		ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL);
181 		bool successfulRead = zvisionSaveMan->readSaveGameHeader(in, header, false);
182 		delete zvisionSaveMan;
183 		delete in;
184 
185 		if (successfulRead) {
186 			SaveStateDescriptor desc(slot, header.saveName);
187 
188 			// Do not allow save slot 0 (used for auto-saving) to be deleted or
189 			// overwritten.
190 			desc.setDeletableFlag(slot != 0);
191 			desc.setWriteProtectedFlag(slot == 0);
192 
193 			desc.setThumbnail(header.thumbnail);
194 
195 			if (header.version >= 1) {
196 				int day = header.saveDay;
197 				int month = header.saveMonth;
198 				int year = header.saveYear;
199 
200 				desc.setSaveDate(year, month, day);
201 
202 				int hour = header.saveHour;
203 				int minutes = header.saveMinutes;
204 
205 				desc.setSaveTime(hour, minutes);
206 			}
207 
208 			if (header.version >= 2) {
209 				desc.setPlayTime(header.playTime * 1000);
210 			}
211 
212 			return desc;
213 		}
214 	}
215 
216 	return SaveStateDescriptor();
217 }
218 
219 #if PLUGIN_ENABLED_DYNAMIC(ZVISION)
220 	REGISTER_PLUGIN_DYNAMIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
221 #else
222 	REGISTER_PLUGIN_STATIC(ZVISION, PLUGIN_TYPE_ENGINE, ZVisionMetaEngine);
223 #endif
224