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