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 "titanic/core/project_item.h"
24 #include "titanic/events.h"
25 #include "titanic/support/simple_file.h"
26 #include "titanic/titanic.h"
27 #include "base/plugins.h"
28 #include "common/savefile.h"
29 #include "common/str-array.h"
30 #include "common/memstream.h"
31 #include "engines/advancedDetector.h"
32 #include "common/system.h"
33 #include "graphics/colormasks.h"
34 #include "graphics/surface.h"
35 
36 namespace Titanic {
37 
38 struct TitanicGameDescription {
39 	ADGameDescription desc;
40 };
41 
getFeatures() const42 uint32 TitanicEngine::getFeatures() const {
43 	return _gameDescription->desc.flags;
44 }
45 
getLanguage() const46 Common::Language TitanicEngine::getLanguage() const {
47 	return _gameDescription->desc.language;
48 }
49 
50 } // End of namespace Titanic
51 
52 static const PlainGameDescriptor TitanicGames[] = {
53 	{"titanic", "Starship Titanic"},
54 	{0, 0}
55 };
56 
57 #include "titanic/detection_tables.h"
58 
59 class TitanicMetaEngine : public AdvancedMetaEngine {
60 public:
TitanicMetaEngine()61 	TitanicMetaEngine() : AdvancedMetaEngine(Titanic::gameDescriptions, sizeof(Titanic::TitanicGameDescription), TitanicGames) {
62 		_maxScanDepth = 3;
63 	}
64 
getName() const65 	virtual const char *getName() const {
66 		return "Starship Titanic";
67 	}
68 
getOriginalCopyright() const69 	virtual const char *getOriginalCopyright() const {
70 		return "Starship Titanic (C) The Digital Village";
71 	}
72 
73 	virtual bool hasFeature(MetaEngineFeature f) const;
74 	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
75 	virtual SaveStateList listSaves(const char *target) const;
76 	virtual int getMaximumSaveSlot() const;
77 	virtual void removeSaveState(const char *target, int slot) const;
78 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
79 };
80 
hasFeature(MetaEngineFeature f) const81 bool TitanicMetaEngine::hasFeature(MetaEngineFeature f) const {
82 	return
83 		(f == kSupportsListSaves) ||
84 		(f == kSupportsLoadingDuringStartup) ||
85 		(f == kSupportsDeleteSave) ||
86 		(f == kSavesSupportMetaInfo) ||
87 		(f == kSavesSupportCreationDate) ||
88 		(f == kSavesSupportPlayTime) ||
89 		(f == kSavesSupportThumbnail) ||
90 		(f == kSimpleSavesNames);
91 }
92 
hasFeature(EngineFeature f) const93 bool Titanic::TitanicEngine::hasFeature(EngineFeature f) const {
94 	return
95 		(f == kSupportsRTL) ||
96 		(f == kSupportsLoadingDuringRuntime) ||
97 		(f == kSupportsSavingDuringRuntime);
98 }
99 
createInstance(OSystem * syst,Engine ** engine,const ADGameDescription * desc) const100 bool TitanicMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
101 	const Titanic::TitanicGameDescription *gd = (const Titanic::TitanicGameDescription *)desc;
102 	*engine = new Titanic::TitanicEngine(syst, gd);
103 
104 	return gd != 0;
105 }
106 
listSaves(const char * target) const107 SaveStateList TitanicMetaEngine::listSaves(const char *target) const {
108 	Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
109 	Common::StringArray filenames;
110 	Common::String saveDesc;
111 	Common::String pattern = Common::String::format("%s.0##", target);
112 	Titanic::TitanicSavegameHeader header;
113 
114 	filenames = saveFileMan->listSavefiles(pattern);
115 
116 	SaveStateList saveList;
117 	for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
118 		const char *ext = strrchr(file->c_str(), '.');
119 		int slot = ext ? atoi(ext + 1) : -1;
120 
121 		if (slot >= 0 && slot <= MAX_SAVES) {
122 			Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
123 
124 			if (in) {
125 				Titanic::CompressedFile cf;
126 				cf.open(in);
127 
128 				if (Titanic::CProjectItem::readSavegameHeader(&cf, header))
129 					saveList.push_back(SaveStateDescriptor(slot, header._saveName));
130 
131 				cf.close();
132 			}
133 		}
134 	}
135 
136 	// Sort saves based on slot number.
137 	Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
138 	return saveList;
139 }
140 
getMaximumSaveSlot() const141 int TitanicMetaEngine::getMaximumSaveSlot() const {
142 	return MAX_SAVES;
143 }
144 
removeSaveState(const char * target,int slot) const145 void TitanicMetaEngine::removeSaveState(const char *target, int slot) const {
146 	Common::String filename = Common::String::format("%s.%03d", target, slot);
147 	g_system->getSavefileManager()->removeSavefile(filename);
148 }
149 
querySaveMetaInfos(const char * target,int slot) const150 SaveStateDescriptor TitanicMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
151 	Common::String filename = Common::String::format("%s.%03d", target, slot);
152 	Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
153 
154 	if (f) {
155 		Titanic::CompressedFile file;
156 		file.open(f);
157 
158 		Titanic::TitanicSavegameHeader header;
159 		if (!Titanic::CProjectItem::readSavegameHeader(&file, header, false)) {
160 			file.close();
161 			return SaveStateDescriptor();
162 		}
163 
164 		file.close();
165 
166 		// Create the return descriptor
167 		SaveStateDescriptor desc(slot, header._saveName);
168 
169 		if (header._version) {
170 			desc.setThumbnail(header._thumbnail);
171 			desc.setSaveDate(header._year, header._month, header._day);
172 			desc.setSaveTime(header._hour, header._minute);
173 			desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
174 		}
175 
176 		return desc;
177 	}
178 
179 	return SaveStateDescriptor();
180 }
181 
182 
183 #if PLUGIN_ENABLED_DYNAMIC(TITANIC)
184 	REGISTER_PLUGIN_DYNAMIC(TITANIC, PLUGIN_TYPE_ENGINE, TitanicMetaEngine);
185 #else
186 	REGISTER_PLUGIN_STATIC(TITANIC, PLUGIN_TYPE_ENGINE, TitanicMetaEngine);
187 #endif
188