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 "gnap/gnap.h"
24
25 #include "common/config-manager.h"
26 #include "engines/advancedDetector.h"
27 #include "common/savefile.h"
28 #include "common/system.h"
29 #include "base/plugins.h"
30 #include "graphics/thumbnail.h"
31
32 static const PlainGameDescriptor gnapGames[] = {
33 { "gnap", "Gnap" },
34 { 0, 0 }
35 };
36
37 namespace Gnap {
38
39 static const ADGameDescription gameDescriptions[] = {
40 {
41 "gnap", "",
42 {
43 {"stock_n.dat", 0, "46819043d019a2f36b727cc2bdd6980f", 12515823},
44 AD_LISTEND
45 },
46 Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, GUIO0()
47 },
48 {
49 "gnap", "",
50 {
51 {"stock_n.dat", 0, "46819043d019a2f36b727cc2bdd6980f", 13497301},
52 AD_LISTEND
53 },
54 Common::EN_ANY, Common::kPlatformWindows, ADGF_NO_FLAGS, GUIO0()
55 },
56 {
57 "gnap", "",
58 {
59 {"stock_n.dat", 0, "46819043d019a2f36b727cc2bdd6980f", 12995485},
60 AD_LISTEND
61 },
62 Common::RU_RUS, Common::kPlatformWindows, ADGF_NO_FLAGS, GUIO0()
63 },
64 {
65 "gnap", "Fargus",
66 {
67 {"stock_n.dat", 0, "46819043d019a2f36b727cc2bdd6980f", 12847726},
68 AD_LISTEND
69 },
70 Common::RU_RUS, Common::kPlatformWindows, ADGF_NO_FLAGS, GUIO0()
71 },
72
73 AD_TABLE_END_MARKER
74 };
75
76 } // End of namespace Gnap
77
78 class GnapMetaEngine : public AdvancedMetaEngine {
79 public:
GnapMetaEngine()80 GnapMetaEngine() : AdvancedMetaEngine(Gnap::gameDescriptions, sizeof(ADGameDescription), gnapGames) {
81 _singleId = "gnap";
82 _maxScanDepth = 3;
83 }
84
getName() const85 virtual const char *getName() const {
86 return "Gnap";
87 }
88
getOriginalCopyright() const89 virtual const char *getOriginalCopyright() const {
90 return "Gnap (C) Artech Digital Entertainment 1997";
91 }
92
93 virtual bool hasFeature(MetaEngineFeature f) const;
94 virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
95 virtual int getMaximumSaveSlot() const;
96 virtual SaveStateList listSaves(const char *target) const;
97 SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
98 virtual void removeSaveState(const char *target, int slot) const;
99 };
100
hasFeature(MetaEngineFeature f) const101 bool GnapMetaEngine::hasFeature(MetaEngineFeature f) const {
102 return
103 (f == kSupportsListSaves) ||
104 (f == kSupportsLoadingDuringStartup) ||
105 (f == kSupportsDeleteSave) ||
106 (f == kSavesSupportMetaInfo) ||
107 (f == kSavesSupportThumbnail) ||
108 (f == kSavesSupportCreationDate) ||
109 (f == kSimpleSavesNames);
110 }
111
hasFeature(EngineFeature f) const112 bool Gnap::GnapEngine::hasFeature(EngineFeature f) const {
113 return
114 (f == kSupportsRTL) ||
115 (f == kSupportsLoadingDuringRuntime) ||
116 (f == kSupportsSavingDuringRuntime);
117 }
118
removeSaveState(const char * target,int slot) const119 void GnapMetaEngine::removeSaveState(const char *target, int slot) const {
120 Common::String fileName = Common::String::format("%s.%03d", target, slot);
121 g_system->getSavefileManager()->removeSavefile(fileName);
122 }
123
getMaximumSaveSlot() const124 int GnapMetaEngine::getMaximumSaveSlot() const { return 99; }
125
listSaves(const char * target) const126 SaveStateList GnapMetaEngine::listSaves(const char *target) const {
127 Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
128 Common::StringArray filenames;
129 Common::String saveDesc;
130 Common::String pattern = Common::String::format("%s.0##", target);
131 Gnap::GnapSavegameHeader header;
132
133 filenames = saveFileMan->listSavefiles(pattern);
134
135 SaveStateList saveList;
136 for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
137 const char *ext = strrchr(file->c_str(), '.');
138 int slot = ext ? atoi(ext + 1) : -1;
139
140 if (slot >= 0 && slot < getMaximumSaveSlot()) {
141 Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
142
143 if (in) {
144 if (Gnap::GnapEngine::readSavegameHeader(in, header))
145 saveList.push_back(SaveStateDescriptor(slot, header._saveName));
146 delete in;
147 }
148 }
149 }
150
151 // Sort saves based on slot number.
152 Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
153 return saveList;
154 }
155
querySaveMetaInfos(const char * target,int slot) const156 SaveStateDescriptor GnapMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
157 Common::String fileName = Common::String::format("%s.%03d", target, slot);
158 Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName);
159 if (file) {
160 char saveIdentBuffer[5];
161 file->read(saveIdentBuffer, 5);
162
163 int32 version = file->readByte();
164 if (version > GNAP_SAVEGAME_VERSION) {
165 delete file;
166 return SaveStateDescriptor();
167 }
168
169 Common::String saveName;
170 char ch;
171 while ((ch = (char)file->readByte()) != '\0')
172 saveName += ch;
173
174 SaveStateDescriptor desc(slot, saveName);
175
176 if (version != 1) {
177 Graphics::Surface *thumbnail;
178 if (!Graphics::loadThumbnail(*file, thumbnail)) {
179 delete file;
180 return SaveStateDescriptor();
181 }
182 desc.setThumbnail(thumbnail);
183 }
184
185 int year = file->readSint16LE();
186 int month = file->readSint16LE();
187 int day = file->readSint16LE();
188 int hour = file->readSint16LE();
189 int minutes = file->readSint16LE();
190
191 desc.setSaveDate(year, month, day);
192 desc.setSaveTime(hour, minutes);
193
194 delete file;
195 return desc;
196 }
197
198 return SaveStateDescriptor();
199 }
200
createInstance(OSystem * syst,Engine ** engine,const ADGameDescription * desc) const201 bool GnapMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
202 if (desc) {
203 *engine = new Gnap::GnapEngine(syst, desc);
204 }
205 return desc != 0;
206 }
207
208 #if PLUGIN_ENABLED_DYNAMIC(GNAP)
209 REGISTER_PLUGIN_DYNAMIC(GNAP, PLUGIN_TYPE_ENGINE, GnapMetaEngine);
210 #else
211 REGISTER_PLUGIN_STATIC(GNAP, PLUGIN_TYPE_ENGINE, GnapMetaEngine);
212 #endif
213