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
27 #include "common/config-manager.h"
28 #include "common/file.h"
29 #include "common/gui_options.h"
30 #include "common/savefile.h"
31 #include "common/system.h"
32 #include "common/translation.h"
33
34 #include "queen/queen.h"
35 #include "queen/resource.h"
36
37 namespace Queen {
38
39 struct QueenGameDescription {
40 ADGameDescription desc;
41 };
42
43 } // End of namespace Queen
44
45 static const PlainGameDescriptor queenGames[] = {
46 {"queen", "Flight of the Amazon Queen"},
47 {0, 0}
48 };
49
50 #define GAMEOPTION_ALT_INTRO GUIO_GAMEOPTIONS1
51
52 static const ADExtraGuiOptionsMap optionsList[] = {
53 {
54 GAMEOPTION_ALT_INTRO,
55 {
56 _s("Alternative intro"),
57 _s("Use an alternative game intro (CD version only)"),
58 "alt_intro",
59 false
60 }
61 },
62
63 AD_EXTRA_GUI_OPTIONS_TERMINATOR
64 };
65
66 namespace Queen {
67
68 static const QueenGameDescription gameDescriptions[] = {
69 // Amiga Demo - English
70 {
71 {
72 "queen",
73 "Demo",
74 AD_ENTRY1s("queen.1", "f7a1a37ac93bf763b1569231237cb4d8", 563335),
75 Common::EN_ANY,
76 Common::kPlatformAmiga,
77 ADGF_DEMO,
78 GUIO1(GUIO_NOSPEECH)
79 },
80 },
81
82 // Amiga Interview Demo - English
83 {
84 {
85 "queen",
86 "Interview",
87 AD_ENTRY1s("queen.1", "f5d42a18d8f5689480413871410663d7", 597032),
88 Common::EN_ANY,
89 Common::kPlatformAmiga,
90 ADGF_DEMO,
91 GUIO1(GUIO_NOSPEECH)
92 },
93 },
94
95 // DOS Demo - English
96 {
97 {
98 "queen",
99 "Demo",
100 AD_ENTRY1s("queen.1", "f39334d8133840aa3bcbd733c12937cf", 3732177),
101 Common::EN_ANY,
102 Common::kPlatformDOS,
103 ADGF_DEMO,
104 GUIO1(GUIO_NOSPEECH)
105 },
106 },
107
108 // DOS Demo - English (from Bugreport #6946)
109 {
110 {
111 "queen",
112 "Demo Alt",
113 AD_ENTRY1s("queen.1", "2871fc6f8090f37fa1a0c556a1c97460", 3735447),
114 Common::EN_ANY,
115 Common::kPlatformDOS,
116 ADGF_DEMO,
117 GUIO1(GUIO_NOSPEECH)
118 },
119 },
120
121 // DOS Interview Demo - English
122 {
123 {
124 "queen",
125 "Interview",
126 AD_ENTRY1s("queen.1", "30b3291f37665bf24d9482b183cb2f67", 1915913),
127 Common::EN_ANY,
128 Common::kPlatformDOS,
129 ADGF_DEMO,
130 GUIO1(GUIO_NOSPEECH)
131 },
132 },
133
134 // DOS Interview Demo - Russian
135 {
136 {
137 "queen",
138 "Interview",
139 AD_ENTRY1s("queen.1c", "246dd55f475c9ea6524c556227fd0383", 1889658),
140 Common::RU_RUS,
141 Common::kPlatformDOS,
142 ADGF_DEMO,
143 GUIO1(GUIO_NOSPEECH)
144 },
145 },
146
147 // PCGAMES DOS Demo - English
148 {
149 {
150 "queen",
151 "Demo",
152 AD_ENTRY1s("queen.1", "f39334d8133840aa3bcbd733c12937cf", 3724538),
153 Common::EN_ANY,
154 Common::kPlatformDOS,
155 ADGF_DEMO,
156 GUIO1(GUIO_NOSPEECH)
157 },
158 },
159
160 // Amiga Floppy - English
161 {
162 {
163 "queen",
164 "Floppy",
165 AD_ENTRY1s("queen.1", "9c209c2cbc1730e3138663c4fd29c2e8", 351775),
166 Common::EN_ANY,
167 Common::kPlatformAmiga,
168 ADGF_NO_FLAGS,
169 GUIO1(GUIO_NOSPEECH)
170 },
171 },
172
173 // DOS Floppy - English
174 {
175 {
176 "queen",
177 "Floppy",
178 AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22677657),
179 Common::EN_ANY,
180 Common::kPlatformDOS,
181 ADGF_NO_FLAGS,
182 GUIO1(GUIO_NOSPEECH)
183 },
184 },
185
186 // DOS CD - English
187 {
188 {
189 "queen",
190 "Talkie",
191 AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190787021),
192 Common::EN_ANY,
193 Common::kPlatformDOS,
194 ADGF_NO_FLAGS,
195 GUIO1(GAMEOPTION_ALT_INTRO)
196 },
197 },
198
199 // DOS Floppy - French
200 {
201 {
202 "queen",
203 "Floppy",
204 AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22157304),
205 Common::FR_FRA,
206 Common::kPlatformDOS,
207 ADGF_NO_FLAGS,
208 GUIO1(GUIO_NOSPEECH)
209 },
210 },
211
212 // DOS Floppy - Russian (From Bugreport #6946)
213 {
214 {
215 "queen",
216 "Floppy",
217 AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22677657),
218 Common::RU_RUS,
219 Common::kPlatformDOS,
220 ADGF_NO_FLAGS,
221 GUIO1(GUIO_NOSPEECH)
222 },
223 },
224
225 // DOS CD - French
226 {
227 {
228 "queen",
229 "Talkie",
230 AD_ENTRY1s("queen.1", "6fd5486a0db75bae2e023b575c3d6a5d", 186689095),
231 Common::FR_FRA,
232 Common::kPlatformDOS,
233 ADGF_NO_FLAGS,
234 GUIO1(GAMEOPTION_ALT_INTRO)
235 },
236 },
237
238 // DOS Floppy - German
239 {
240 {
241 "queen",
242 "Floppy",
243 AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22240013),
244 Common::DE_DEU,
245 Common::kPlatformDOS,
246 ADGF_NO_FLAGS,
247 GUIO1(GUIO_NOSPEECH)
248 },
249 },
250
251 // DOS CD - German
252 {
253 {
254 "queen",
255 "Talkie",
256 AD_ENTRY1s("queen.1", "551d595be8af890fc4cb8533c9c5f5f1", 217648975),
257 Common::DE_DEU,
258 Common::kPlatformDOS,
259 ADGF_NO_FLAGS,
260 GUIO1(GAMEOPTION_ALT_INTRO)
261 },
262 },
263
264 #if 0
265 // DOS CD - Hebrew
266 {
267 {
268 "queen",
269 "Talkie",
270 AD_ENTRY1s("queen.1", NULL, 190705558), // TODO: Fill in correct MD5
271 Common::HE_ISR,
272 Common::kPlatformDOS,
273 ADGF_NO_FLAGS,
274 GUIO1(GAMEOPTION_ALT_INTRO)
275 },
276 },
277 #endif
278
279 // DOS Floppy - Italian
280 {
281 {
282 "queen",
283 "Floppy",
284 AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22461366),
285 Common::IT_ITA,
286 Common::kPlatformDOS,
287 ADGF_NO_FLAGS,
288 GUIO1(GUIO_NOSPEECH)
289 },
290 },
291
292 // DOS CD - Italian
293 {
294 {
295 "queen",
296 "Talkie",
297 AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190795582),
298 Common::IT_ITA,
299 Common::kPlatformDOS,
300 ADGF_NO_FLAGS,
301 GUIO1(GAMEOPTION_ALT_INTRO)
302 },
303 },
304
305 // DOS CD - Spanish
306 {
307 {
308 "queen",
309 "Talkie",
310 AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190730602),
311 Common::ES_ESP,
312 Common::kPlatformDOS,
313 ADGF_NO_FLAGS,
314 GUIO1(GAMEOPTION_ALT_INTRO)
315 },
316 },
317
318 // DOS CD - English (Compressed Freeware Release v1.0)
319 {
320 {
321 "queen",
322 "Talkie",
323 AD_ENTRY1s("queen.1c", "a0749bb8b72e537ead1a63a3dde1443d", 54108887),
324 Common::EN_ANY,
325 Common::kPlatformDOS,
326 ADGF_NO_FLAGS,
327 GUIO1(GAMEOPTION_ALT_INTRO)
328 },
329 },
330
331 // DOS CD - English (Compressed Freeware Release v1.1)
332 {
333 {
334 "queen",
335 "Talkie",
336 AD_ENTRY1s("queen.1c", "21fd690b372f8a6289f6f33bc986276c", 51222412),
337 Common::EN_ANY,
338 Common::kPlatformDOS,
339 ADGF_NO_FLAGS,
340 GUIO1(GAMEOPTION_ALT_INTRO)
341 },
342 },
343
344 // DOS CD - French (Compressed Freeware Release v1.0)
345 {
346 {
347 "queen",
348 "Talkie",
349 AD_ENTRY1s("queen.1c", "67e3020f8a35e1df7b1c753b5aaa71e1", 97382620),
350 Common::FR_FRA,
351 Common::kPlatformDOS,
352 ADGF_NO_FLAGS,
353 GUIO1(GAMEOPTION_ALT_INTRO)
354 },
355 },
356
357 // DOS CD - German (Compressed Freeware Release v1.0)
358 {
359 {
360 "queen",
361 "Talkie",
362 AD_ENTRY1s("queen.1c", "28f78dbec7e20f603a10c2f8ea889a5c", 108738717),
363 Common::DE_DEU,
364 Common::kPlatformDOS,
365 ADGF_NO_FLAGS,
366 GUIO1(GAMEOPTION_ALT_INTRO)
367 },
368 },
369
370 // DOS CD - Hebrew (Compressed Freeware Release v1.0)
371 {
372 {
373 "queen",
374 "Talkie",
375 AD_ENTRY1s("queen.1c", "4d52d8780613ef27a2b779caecb20a21", 99391805),
376 Common::HE_ISR,
377 Common::kPlatformDOS,
378 ADGF_NO_FLAGS,
379 GUIO1(GAMEOPTION_ALT_INTRO)
380 },
381 },
382
383 // DOS CD - Italian (Compressed Freeware Release v1.0)
384 {
385 {
386 "queen",
387 "Talkie",
388 AD_ENTRY1s("queen.1c", "2f72b715ed753cf905a37cdcc7ea611e", 98327801),
389 Common::IT_ITA,
390 Common::kPlatformDOS,
391 ADGF_NO_FLAGS,
392 GUIO1(GAMEOPTION_ALT_INTRO)
393 },
394 },
395
396 // DOS CD - Hungarian (Compressed Freeware Release v1.02)
397 {
398 {
399 "queen",
400 "Talkie",
401 AD_ENTRY1s("queen.1c", "21fd690b372f8a6289f6f33bc986276c", 51329031),
402 Common::HU_HUN,
403 Common::kPlatformDOS,
404 ADGF_NO_FLAGS,
405 GUIO1(GAMEOPTION_ALT_INTRO)
406 },
407 },
408
409 // DOS CD - Russian (Compressed Freeware Release v1.0)
410 {
411 {
412 "queen",
413 "Talkie",
414 AD_ENTRY1s("queen.1c", "908d04940d40537d32c50a8429cd8631", 51222412),
415 Common::RU_RUS,
416 Common::kPlatformDOS,
417 ADGF_NO_FLAGS,
418 GUIO1(GAMEOPTION_ALT_INTRO)
419 },
420 },
421
422 // TODO: Freeware Release for Spanish DOS CD is missing.
423 #if 0
424 // DOS CD - Spanish (Compressed Freeware Release v1.0)
425 {
426 {
427 "queen",
428 "Talkie",
429 AD_ENTRY1s("queen.1c", NULL, ?),
430 Common::ES_ESP,
431 Common::kPlatformDOS,
432 ADGF_NO_FLAGS,
433 GUIO1(GAMEOPTION_ALT_INTRO)
434 },
435 },
436 #endif
437
438 // GoG.com Release - German
439 {
440 {
441 "queen",
442 "Talkie",
443 AD_ENTRY1s("queen.1", "28f78dbec7e20f603a10c2f8ea889a5c", 108738717),
444 Common::DE_DEU,
445 Common::kPlatformDOS,
446 ADGF_NO_FLAGS,
447 GUIO1(GAMEOPTION_ALT_INTRO)
448 },
449 },
450
451 // GoG.com Release - French
452 {
453 {
454 "queen",
455 "Talkie",
456 AD_ENTRY1s("queen.1", "67e3020f8a35e1df7b1c753b5aaa71e1", 97382620),
457 Common::FR_FRA,
458 Common::kPlatformDOS,
459 ADGF_NO_FLAGS,
460 GUIO1(GAMEOPTION_ALT_INTRO)
461 },
462 },
463
464 // GoG.com Release - Italian
465 {
466 {
467 "queen",
468 "Talkie",
469 AD_ENTRY1s("queen.1", "2f72b715ed753cf905a37cdcc7ea611e", 98327801),
470 Common::IT_ITA,
471 Common::kPlatformDOS,
472 ADGF_NO_FLAGS,
473 GUIO1(GAMEOPTION_ALT_INTRO)
474 },
475 },
476
477 { AD_TABLE_END_MARKER }
478 };
479
480 } // End of namespace Queen
481
482 class QueenMetaEngine : public AdvancedMetaEngine {
483 public:
QueenMetaEngine()484 QueenMetaEngine() : AdvancedMetaEngine(Queen::gameDescriptions, sizeof(Queen::QueenGameDescription), queenGames, optionsList) {
485 _singleId = "queen";
486 }
487
getName() const488 virtual const char *getName() const {
489 return "Flight of the Amazon Queen";
490 }
491
getOriginalCopyright() const492 virtual const char *getOriginalCopyright() const {
493 return "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis";
494 }
495
496 virtual bool hasFeature(MetaEngineFeature f) const;
497 virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
498 virtual SaveStateList listSaves(const char *target) const;
getMaximumSaveSlot() const499 virtual int getMaximumSaveSlot() const { return 99; }
500 virtual void removeSaveState(const char *target, int slot) const;
501
502 ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
503 };
504
hasFeature(MetaEngineFeature f) const505 bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const {
506 return
507 (f == kSupportsListSaves) ||
508 (f == kSupportsLoadingDuringStartup) ||
509 (f == kSupportsDeleteSave);
510 }
511
fallbackDetect(const FileMap & allFiles,const Common::FSList & fslist) const512 ADDetectedGame QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
513 static ADGameDescription desc;
514
515 // Iterate over all files in the given directory
516 for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
517 if (file->isDirectory()) {
518 continue;
519 }
520 if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) {
521 Common::File dataFile;
522 if (!dataFile.open(*file)) {
523 continue;
524 }
525 Queen::DetectedGameVersion version;
526 if (Queen::Resource::detectVersion(&version, &dataFile)) {
527 desc.gameId = "queen";
528 desc.language = version.language;
529 desc.platform = version.platform;
530 desc.flags = ADGF_NO_FLAGS;
531 desc.guiOptions = GUIO0();
532 if (version.features & Queen::GF_DEMO) {
533 desc.extra = "Demo";
534 desc.flags = ADGF_DEMO;
535 desc.guiOptions = GUIO_NOSPEECH;
536 } else if (version.features & Queen::GF_INTERVIEW) {
537 desc.extra = "Interview";
538 desc.flags = ADGF_DEMO;
539 desc.guiOptions = GUIO_NOSPEECH;
540 } else if (version.features & Queen::GF_FLOPPY) {
541 desc.extra = "Floppy";
542 desc.guiOptions = GUIO_NOSPEECH;
543 } else if (version.features & Queen::GF_TALKIE) {
544 desc.extra = "Talkie";
545 desc.guiOptions = GAMEOPTION_ALT_INTRO;
546 }
547
548 return ADDetectedGame(&desc);
549 }
550 }
551 }
552
553 return ADDetectedGame();
554 }
555
listSaves(const char * target) const556 SaveStateList QueenMetaEngine::listSaves(const char *target) const {
557 Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
558 Common::StringArray filenames;
559 char saveDesc[32];
560 Common::String pattern("queen.s##");
561
562 filenames = saveFileMan->listSavefiles(pattern);
563
564 SaveStateList saveList;
565 for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
566 // Obtain the last 2 digits of the filename, since they correspond to the save slot
567 int slotNum = atoi(file->c_str() + file->size() - 2);
568
569 if (slotNum >= 0 && slotNum <= 99) {
570 Common::InSaveFile *in = saveFileMan->openForLoading(*file);
571 if (in) {
572 for (int i = 0; i < 4; i++)
573 in->readUint32BE();
574 in->read(saveDesc, 32);
575 saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
576 delete in;
577 }
578 }
579 }
580
581 // Sort saves based on slot number.
582 Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
583 return saveList;
584 }
585
removeSaveState(const char * target,int slot) const586 void QueenMetaEngine::removeSaveState(const char *target, int slot) const {
587 Common::String filename = Common::String::format("queen.s%02d", slot);
588
589 g_system->getSavefileManager()->removeSavefile(filename);
590 }
591
createInstance(OSystem * syst,Engine ** engine,const ADGameDescription * desc) const592 bool QueenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
593 const Queen::QueenGameDescription *gd = (const Queen::QueenGameDescription *)desc;
594
595 if (gd)
596 *engine = new Queen::QueenEngine(syst); //FIXME , gd);
597
598 return (gd != 0);
599 }
600
601 #if PLUGIN_ENABLED_DYNAMIC(QUEEN)
602 REGISTER_PLUGIN_DYNAMIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine);
603 #else
604 REGISTER_PLUGIN_STATIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine);
605 #endif
606