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 "graphics/thumbnail.h"
24
25 #include "engines/advancedDetector.h"
26
27 #include "common/savefile.h"
28 #include "common/system.h"
29
30 #include "cge/cge.h"
31
32 namespace CGE {
33
34 class CGEMetaEngine : public AdvancedMetaEngine {
35 public:
getName() const36 const char *getName() const override {
37 return "cge";
38 }
39
40 bool hasFeature(MetaEngineFeature f) const override;
41
42 Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
43
44 int getMaximumSaveSlot() const override;
45 SaveStateList listSaves(const char *target) const override;
46 SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
47 void removeSaveState(const char *target, int slot) const override;
48 };
49
hasFeature(MetaEngineFeature f) const50 bool CGEMetaEngine::hasFeature(MetaEngineFeature f) const {
51 return
52 (f == kSupportsListSaves) ||
53 (f == kSupportsLoadingDuringStartup) ||
54 (f == kSupportsDeleteSave) ||
55 (f == kSavesSupportMetaInfo) ||
56 (f == kSavesSupportThumbnail) ||
57 (f == kSavesSupportCreationDate) ||
58 (f == kSavesSupportPlayTime) ||
59 (f == kSimpleSavesNames);
60 }
61
removeSaveState(const char * target,int slot) const62 void CGEMetaEngine::removeSaveState(const char *target, int slot) const {
63 Common::String fileName = Common::String::format("%s.%03d", target, slot);
64 g_system->getSavefileManager()->removeSavefile(fileName);
65 }
66
getMaximumSaveSlot() const67 int CGEMetaEngine::getMaximumSaveSlot() const {
68 return 99;
69 }
70
listSaves(const char * target) const71 SaveStateList CGEMetaEngine::listSaves(const char *target) const {
72 Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
73 Common::StringArray filenames;
74 Common::String pattern = target;
75 pattern += ".###";
76
77 filenames = saveFileMan->listSavefiles(pattern);
78
79 SaveStateList saveList;
80 for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
81 // Obtain the last 3 digits of the filename, since they correspond to the save slot
82 int slotNum = atoi(filename->c_str() + filename->size() - 3);
83
84 if (slotNum >= 0 && slotNum <= 99) {
85
86 Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
87 if (file) {
88 CGE::SavegameHeader header;
89
90 // Check to see if it's a ScummVM savegame or not
91 char buffer[kSavegameStrSize + 1];
92 file->read(buffer, kSavegameStrSize + 1);
93
94 if (!strncmp(buffer, CGE::savegameStr, kSavegameStrSize + 1)) {
95 // Valid savegame
96 if (CGE::CGEEngine::readSavegameHeader(file, header)) {
97 saveList.push_back(SaveStateDescriptor(this, slotNum, header.saveName));
98 }
99 } else {
100 // Must be an original format savegame
101 saveList.push_back(SaveStateDescriptor(this, slotNum, "Unknown"));
102 }
103
104 delete file;
105 }
106 }
107 }
108
109 // Sort saves based on slot number.
110 Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
111 return saveList;
112 }
113
querySaveMetaInfos(const char * target,int slot) const114 SaveStateDescriptor CGEMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
115 Common::String fileName = Common::String::format("%s.%03d", target, slot);
116 Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
117
118 if (f) {
119 CGE::SavegameHeader header;
120
121 // Check to see if it's a ScummVM savegame or not
122 char buffer[kSavegameStrSize + 1];
123 f->read(buffer, kSavegameStrSize + 1);
124
125 bool hasHeader = !strncmp(buffer, CGE::savegameStr, kSavegameStrSize + 1) &&
126 CGE::CGEEngine::readSavegameHeader(f, header, false);
127 delete f;
128
129 if (!hasHeader) {
130 // Original savegame perhaps?
131 SaveStateDescriptor desc(this, slot, "Unknown");
132 return desc;
133 } else {
134 // Create the return descriptor
135 SaveStateDescriptor desc(this, slot, header.saveName);
136 desc.setThumbnail(header.thumbnail);
137 desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
138 desc.setSaveTime(header.saveHour, header.saveMinutes);
139
140 if (header.playTime) {
141 desc.setPlayTime(header.playTime * 1000);
142 }
143
144 return desc;
145 }
146 }
147
148 return SaveStateDescriptor();
149 }
150
createInstance(OSystem * syst,Engine ** engine,const ADGameDescription * desc) const151 Common::Error CGEMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
152 *engine = new CGE::CGEEngine(syst, desc);
153 return Common::kNoError;
154 }
155
156 } // End of namespace CGE
157
158 #if PLUGIN_ENABLED_DYNAMIC(CGE)
159 REGISTER_PLUGIN_DYNAMIC(CGE, PLUGIN_TYPE_ENGINE, CGE::CGEMetaEngine);
160 #else
161 REGISTER_PLUGIN_STATIC(CGE, PLUGIN_TYPE_ENGINE, CGE::CGEMetaEngine);
162 #endif
163