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 "base/plugins.h"
24
25 #include "engines/advancedDetector.h"
26 #include "common/file.h"
27
28 #include "neverhood/neverhood.h"
29 #include "neverhood/detection.h"
30
31 namespace Neverhood {
32
getGameId() const33 const char *NeverhoodEngine::getGameId() const {
34 return _gameDescription->gameId;
35 }
36
getPlatform() const37 Common::Platform NeverhoodEngine::getPlatform() const {
38 return _gameDescription->platform;
39 }
40
getLanguage() const41 Common::Language NeverhoodEngine::getLanguage() const {
42 return _gameDescription->language;
43 }
44
isDemo() const45 bool NeverhoodEngine::isDemo() const {
46 return _gameDescription->flags & ADGF_DEMO;
47 }
48
isBigDemo() const49 bool NeverhoodEngine::isBigDemo() const {
50 return _gameDescription->flags & GF_BIG_DEMO;
51 }
52
applyResourceFixes() const53 bool NeverhoodEngine::applyResourceFixes() const {
54 return getLanguage() == Common::RU_RUS;
55 }
56
57 } // End of namespace Neverhood
58
59 class NeverhoodMetaEngine : public AdvancedMetaEngine {
60 public:
getName() const61 const char *getName() const override {
62 return "neverhood";
63 }
64
65 bool hasFeature(MetaEngineFeature f) const override;
66 Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
67
68 SaveStateList listSaves(const char *target) const override;
69 int getMaximumSaveSlot() const override;
70 void removeSaveState(const char *target, int slot) const override;
71 SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
72 };
73
hasFeature(MetaEngineFeature f) const74 bool NeverhoodMetaEngine::hasFeature(MetaEngineFeature f) const {
75 return
76 (f == kSupportsListSaves) ||
77 (f == kSupportsLoadingDuringStartup) ||
78 (f == kSupportsDeleteSave) ||
79 (f == kSavesSupportMetaInfo) ||
80 (f == kSavesSupportThumbnail) ||
81 (f == kSavesSupportCreationDate) ||
82 (f == kSavesSupportPlayTime) ||
83 (f == kSimpleSavesNames);
84 }
85
hasFeature(EngineFeature f) const86 bool Neverhood::NeverhoodEngine::hasFeature(EngineFeature f) const {
87 return
88 (f == kSupportsReturnToLauncher) ||
89 (f == kSupportsLoadingDuringRuntime) ||
90 (f == kSupportsSavingDuringRuntime);
91 }
92
createInstance(OSystem * syst,Engine ** engine,const ADGameDescription * desc) const93 Common::Error NeverhoodMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
94 *engine = new Neverhood::NeverhoodEngine(syst, desc);
95 return Common::kNoError;
96 }
97
listSaves(const char * target) const98 SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const {
99 Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
100 Neverhood::NeverhoodEngine::SaveHeader header;
101 Common::String pattern = target;
102 pattern += ".###";
103
104 Common::StringArray filenames;
105 filenames = saveFileMan->listSavefiles(pattern.c_str());
106
107 SaveStateList saveList;
108 for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
109 // Obtain the last 3 digits of the filename, since they correspond to the save slot
110 int slotNum = atoi(file->c_str() + file->size() - 3);
111 if (slotNum >= 0 && slotNum <= 999) {
112 Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
113 if (in) {
114 if (Neverhood::NeverhoodEngine::readSaveHeader(in, header) == Neverhood::NeverhoodEngine::kRSHENoError) {
115 saveList.push_back(SaveStateDescriptor(this, slotNum, header.description));
116 }
117 delete in;
118 }
119 }
120 }
121
122 // Sort saves based on slot number.
123 Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
124 return saveList;
125 }
126
getMaximumSaveSlot() const127 int NeverhoodMetaEngine::getMaximumSaveSlot() const {
128 return 999;
129 }
130
removeSaveState(const char * target,int slot) const131 void NeverhoodMetaEngine::removeSaveState(const char *target, int slot) const {
132 Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
133 Common::String filename = Neverhood::NeverhoodEngine::getSavegameFilename(target, slot);
134 saveFileMan->removeSavefile(filename.c_str());
135 }
136
querySaveMetaInfos(const char * target,int slot) const137 SaveStateDescriptor NeverhoodMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
138 Common::String filename = Neverhood::NeverhoodEngine::getSavegameFilename(target, slot);
139 Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
140
141 if (in) {
142 Neverhood::NeverhoodEngine::SaveHeader header;
143 Neverhood::NeverhoodEngine::kReadSaveHeaderError error;
144
145 error = Neverhood::NeverhoodEngine::readSaveHeader(in, header, false);
146 delete in;
147
148 if (error == Neverhood::NeverhoodEngine::kRSHENoError) {
149 SaveStateDescriptor desc(this, slot, header.description);
150
151 desc.setThumbnail(header.thumbnail);
152 int day = (header.saveDate >> 24) & 0xFF;
153 int month = (header.saveDate >> 16) & 0xFF;
154 int year = header.saveDate & 0xFFFF;
155 desc.setSaveDate(year, month, day);
156 int hour = (header.saveTime >> 16) & 0xFF;
157 int minutes = (header.saveTime >> 8) & 0xFF;
158 desc.setSaveTime(hour, minutes);
159 desc.setPlayTime(header.playTime * 1000);
160 return desc;
161 }
162 }
163
164 return SaveStateDescriptor();
165 }
166
167 #if PLUGIN_ENABLED_DYNAMIC(NEVERHOOD)
168 REGISTER_PLUGIN_DYNAMIC(NEVERHOOD, PLUGIN_TYPE_ENGINE, NeverhoodMetaEngine);
169 #else
170 REGISTER_PLUGIN_STATIC(NEVERHOOD, PLUGIN_TYPE_ENGINE, NeverhoodMetaEngine);
171 #endif
172