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