/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * Based on the Reverse Engineering work of Christophe Fontanel, * maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/) */ #include "common/config-manager.h" #include "common/error.h" #include "common/fs.h" #include "common/system.h" #include "common/translation.h" #include "engines/advancedDetector.h" #include "dm/dm.h" #include "backends/keymapper/action.h" #include "backends/keymapper/keymapper.h" #include "backends/keymapper/standard-actions.h" namespace DM { class DMMetaEngine : public AdvancedMetaEngine { public: const char *getName() const override { return "dm"; } Common::Error createInstance(OSystem *syst, Engine **engine, const DMADGameDescription *desc) const override { *engine = new DM::DMEngine(syst, (const DMADGameDescription*)desc); return Common::kNoError; } bool hasFeature(MetaEngineFeature f) const override { return (f == kSupportsListSaves) || (f == kSupportsLoadingDuringStartup) || (f == kSavesSupportThumbnail) || (f == kSavesSupportMetaInfo) || (f == kSimpleSavesNames) || (f == kSavesSupportCreationDate); } int getMaximumSaveSlot() const override { return 99; } SaveStateList listSaves(const char *target) const override { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); SaveGameHeader header; Common::String pattern = target; pattern += ".###"; Common::StringArray filenames = saveFileMan->listSavefiles(pattern.c_str()); SaveStateList saveList; for (const auto &filename : filenames) { // Obtain the last 3 digits of the filename, since they correspond to the save slot int slotNum = atoi(filename.c_str() + filename.size() - 3); if ((slotNum >= 0) && (slotNum <= 999)) { Common::InSaveFile *in = saveFileMan->openForLoading(filename.c_str()); if (in) { if (DM::readSaveGameHeader(in, &header)) saveList.push_back(SaveStateDescriptor(this, slotNum, header._descr.getDescription())); delete in; } } } // Sort saves based on slot number. Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); return saveList; } SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override { Common::String filename = Common::String::format("%s.%03u", target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str()); if (in) { DM::SaveGameHeader header; bool successfulRead = DM::readSaveGameHeader(in, &header); delete in; if (successfulRead) { SaveStateDescriptor desc(this, slot, header._descr.getDescription()); return header._descr; } } return SaveStateDescriptor(); } bool removeSaveState(const char *target, int slot) const override { return false; } Common::KeymapArray initKeymaps(const char *target) const override; }; Common::KeymapArray DMMetaEngine::initKeymaps(const char *target) const { using namespace Common; using namespace DM; Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "dm-default", _("Default keymappings")); Keymap *choiceSelectionKeyMap = new Keymap(Keymap::kKeymapTypeGame, "choice-selection", _("Dialog choice selection keymappings")); Keymap *gameKeyMap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings")); Action *act; act = new Action(kStandardActionLeftClick, _("Select / Interact")); act->setLeftClickEvent(); act->addDefaultInputMapping("MOUSE_LEFT"); act->addDefaultInputMapping("JOY_A"); engineKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The player has a team of 4 characters called "champions" which they choose themselves. One of them can be assigned the "leader". This action toggles the inventory screen of the leader champion. act = new Action(kStandardActionRightClick, _("Toggle leader inventory")); act->setRightClickEvent(); act->addDefaultInputMapping("MOUSE_RIGHT"); act->addDefaultInputMapping("JOY_B"); engineKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The game has multi-choice dialogs. If there is only one choice, then this action can be used to select it. act = new Action("SELECTCHOICE", _("Select dialog choice (only works if there is a single choice)")); act->setCustomEngineActionEvent(kActionSelectChoice); act->addDefaultInputMapping("RETURN"); act->addDefaultInputMapping("JOY_X"); choiceSelectionKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The player has a team of 4 characters called "champions" which they choose themselves. This action toggles the inventory screen of champion 1. act = new Action("CHAMPION1INV", _("Toggle champion 1 inventory")); act->setCustomEngineActionEvent(kActionToggleInventoryChampion0); act->addDefaultInputMapping("F1"); // F1 (1~) Atari ST: Code = 0x3B00 gameKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The player has a team of 4 characters called "champions" which they choose themselves. This action toggles the inventory screen of champion 2. act = new Action("CHAMPION2INV", _("Toggle champion 2 inventory")); act->setCustomEngineActionEvent(kActionToggleInventoryChampion1); act->addDefaultInputMapping("F2"); // F2 (2~) Atari ST: Code = 0x3C00 gameKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The player has a team of 4 characters called "champions" which they choose themselves. This action toggles the inventory screen of champion 3. act = new Action("CHAMPION3INV", _("Toggle champion 3 inventory")); act->setCustomEngineActionEvent(kActionToggleInventoryChampion2); act->addDefaultInputMapping("F3"); // F3 (3~) Atari ST: Code = 0x3D00 gameKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The player has a team of 4 characters called "champions" which they choose themselves. This action toggles the inventory screen of champion 4. act = new Action("CHAMPION4INV", _("Toggle champion 4 inventory")); act->setCustomEngineActionEvent(kActionToggleInventoryChampion3); act->addDefaultInputMapping("F4"); // F4 (4~) Atari ST: Code = 0x3E00 gameKeyMap->addAction(act); act = new Action("SAVEGAME", _("Save game")); act->setCustomEngineActionEvent(kActionSave); act->addDefaultInputMapping("C+s"); // CTRL-S Atari ST: Code = 0x0013 act->addDefaultInputMapping("JOY_X"); gameKeyMap->addAction(act); act = new Action("FREEZE", _("Pause")); act->setCustomEngineActionEvent(kActionFreezeGame); act->addDefaultInputMapping("ESCAPE"); // Esc (0x1B) Atari ST: Code = 0x001B act->addDefaultInputMapping("JOY_Y"); gameKeyMap->addAction(act); act = new Action("TURNLEFT", _("Turn left")); act->setCustomEngineActionEvent(kActionTurnLeft); act->addDefaultInputMapping("KP4"); // Numeric pad 4 Atari ST: Code = 0x5200 act->addDefaultInputMapping("q"); // Added for convenience act->addDefaultInputMapping("S+q"); // Added for convenience act->addDefaultInputMapping("DELETE"); // Del (0x7F) act->addDefaultInputMapping("S+DELETE"); // Shift Del (0x7F) act->addDefaultInputMapping("JOY_LEFT_SHOULDER"); gameKeyMap->addAction(act); act = new Action("MOVEFORWARD", _("Move forward")); act->setCustomEngineActionEvent(kActionMoveForward); act->addDefaultInputMapping("KP4"); // Numeric pad 5 Atari ST: Code = 0x4800 act->addDefaultInputMapping("w"); // Added for convenience act->addDefaultInputMapping("S+w"); // Added for convenience act->addDefaultInputMapping("UP"); // Up Arrow (A) act->addDefaultInputMapping("S+UP"); // Shift Up Arrow (T) act->addDefaultInputMapping("JOY_UP"); gameKeyMap->addAction(act); act = new Action("TURNRIGHT", _("Turn right")); act->setCustomEngineActionEvent(kActionTurnRight); act->addDefaultInputMapping("KP6"); // Numeric pad 6 Atari ST: Code = 0x4700 act->addDefaultInputMapping("e"); // Added for convenience act->addDefaultInputMapping("S+e"); // Added for convenience act->addDefaultInputMapping("HELP"); // Help (?~) act->addDefaultInputMapping("S+HELP"); // Shift Help (?~) act->addDefaultInputMapping("JOY_RIGHT_SHOULDER"); gameKeyMap->addAction(act); act = new Action("MOVELEFT", _("Strafe left")); act->setCustomEngineActionEvent(kActionMoveLeft); act->addDefaultInputMapping("KP1"); // Numeric pad 1 Atari ST: Code = 0x4B00 act->addDefaultInputMapping("a"); // Added for convenience act->addDefaultInputMapping("S+a"); // Added for convenience act->addDefaultInputMapping("LEFT"); // Backward Arrow (D) act->addDefaultInputMapping("S+LEFT"); // Shift Backward Arrow (V) act->addDefaultInputMapping("JOY_LEFT"); gameKeyMap->addAction(act); act = new Action("MOVEBACKWARD", _("Move backward")); act->setCustomEngineActionEvent(kActionMoveBackward); act->addDefaultInputMapping("KP2"); // Numeric pad 2 Atari ST: Code = 0x5000 act->addDefaultInputMapping("s"); // Added for convenience act->addDefaultInputMapping("S+s"); // Added for convenience act->addDefaultInputMapping("DOWN"); // Down Arrow (B) act->addDefaultInputMapping("S+DOWN"); // Shift Down Arrow (S) act->addDefaultInputMapping("JOY_DOWN"); gameKeyMap->addAction(act); act = new Action("MOVERIGHT", _("Strafe right")); act->setCustomEngineActionEvent(kActionMoveRight); act->addDefaultInputMapping("KP3"); // Numeric pad 3 Atari ST: Code = 0x4D00. act->addDefaultInputMapping("d"); // Added for convenience act->addDefaultInputMapping("S+d"); // Added for convenience act->addDefaultInputMapping("RIGHT"); // Forward Arrow (C) act->addDefaultInputMapping("S+RIGHT"); // Shift Forward Arrow (U) act->addDefaultInputMapping("JOY_RIGHT"); gameKeyMap->addAction(act); // I18N: (Game name: Dungeon Master) The player has a team of 4 characters called "champions" which they choose themselves. The champions can be put to sleep. This action wakes up the sleeping champion. act = new Action("WAKEUPCHAMPION", _("Wake up champion")); act->setCustomEngineActionEvent(kActionWakeUp); act->addDefaultInputMapping("RETURN"); gameKeyMap->addAction(act); KeymapArray keymaps(3); keymaps[0] = engineKeyMap; keymaps[1] = choiceSelectionKeyMap; keymaps[2] = gameKeyMap; choiceSelectionKeyMap->setEnabled(false); return keymaps; } } // End of namespace DM #if PLUGIN_ENABLED_DYNAMIC(DM) REGISTER_PLUGIN_DYNAMIC(DM, PLUGIN_TYPE_ENGINE, DM::DMMetaEngine); #else REGISTER_PLUGIN_STATIC(DM, PLUGIN_TYPE_ENGINE, DM::DMMetaEngine); #endif