ScummVM API documentation
adl.h
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 modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (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, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef ADL_ADL_H
23#define ADL_ADL_H
24
25#include "common/debug-channels.h"
26#include "common/array.h"
27#include "common/rect.h"
28#include "common/str.h"
29#include "common/hashmap.h"
30#include "common/hash-str.h"
31#include "common/func.h"
32#include "common/ptr.h"
33#include "common/scummsys.h"
34#include "common/keyboard.h"
35
36#include "engines/engine.h"
37
38#include "audio/mixer.h"
39#include "audio/softsynth/pcspk.h"
40
41#include "adl/console.h"
42#include "adl/disk.h"
43#include "adl/sound.h"
44#include "adl/detection.h"
45
46namespace Common {
47class ReadStream;
48class WriteStream;
49class SeekableReadStream;
50class File;
51struct Event;
52class RandomSource;
53}
54
55namespace Adl {
56
57Common::Path getDiskImageName(const AdlGameDescription &adlDesc, byte volume);
58GameType getGameType(const AdlGameDescription &desc);
59GameVersion getGameVersion(const AdlGameDescription &desc);
60Common::Language getLanguage(const AdlGameDescription &desc);
61Common::Platform getPlatform(const AdlGameDescription &desc);
62
63class Console;
64class Display;
65class GraphicsMan;
66class ScriptEnv;
67
68enum kDebugChannels {
69 kDebugChannelScript = 1,
70};
71
72enum ADLAction {
73 kADLActionNone,
74 kADLActionQuit,
75
76 kADLActionCount
77};
78
79// Save and restore opcodes
80#define IDO_ACT_SAVE 0x0f
81#define IDO_ACT_LOAD 0x10
82
83#define IDI_CUR_ROOM 0xfc
84#define IDI_VOID_ROOM 0xfd
85#define IDI_ANY 0xfe
86
87#define IDI_WORD_SIZE 8
88
89enum Direction {
90 IDI_DIR_NORTH,
91 IDI_DIR_SOUTH,
92 IDI_DIR_EAST,
93 IDI_DIR_WEST,
94 IDI_DIR_UP,
95 IDI_DIR_DOWN,
96 IDI_DIR_TOTAL
97};
98
99struct Room {
100 Room() :
101 description(0),
102 picture(0),
103 curPicture(0),
104 isFirstTime(true) {
105 memset(connections, 0, sizeof(connections));
106 }
107
108 byte description;
109 byte connections[IDI_DIR_TOTAL];
111 byte picture;
112 byte curPicture;
113 bool isFirstTime;
114};
115
117
119
120struct Command {
121 byte room;
122 byte verb, noun;
123 byte numCond, numAct;
124 Script script;
125};
126
128public:
129 ScriptEnv(const Command &cmd, byte room, byte verb, byte noun) :
130 _cmd(cmd), _room(room), _verb(verb), _noun(noun), _ip(0) { }
131
132 virtual ~ScriptEnv() { }
133
134 enum kOpType {
135 kOpTypeDone,
136 kOpTypeCond,
137 kOpTypeAct
138 };
139
140 byte op() const { return _cmd.script[_ip]; }
141 virtual kOpType getOpType() const = 0;
142 // We keep this 1-based for easier comparison with the original engine
143 byte arg(uint i) const { return _cmd.script[_ip + i]; }
144 virtual void next(uint numArgs) = 0;
145
146 bool isMatch() const {
147 return (_cmd.room == IDI_ANY || _cmd.room == _room) &&
148 (_cmd.verb == IDI_ANY || _cmd.verb == _verb) &&
149 (_cmd.noun == IDI_ANY || _cmd.noun == _noun);
150 }
151
152 byte getNoun() const { return _noun; }
153 const Command &getCommand() const { return _cmd; }
154
155protected:
156 byte _ip;
157
158private:
159 const Command &_cmd;
160 const byte _room, _verb, _noun;
161};
162
163enum {
164 IDI_ITEM_NOT_MOVED,
165 IDI_ITEM_DROPPED,
166 IDI_ITEM_DOESNT_MOVE
167};
168
169struct Item {
170 byte id;
171 byte noun;
172 byte region;
173 byte room;
174 byte picture;
175 bool isShape;
176 Common::Point position;
177 int state;
178 byte description;
179 Common::Array<byte> roomPictures;
180 bool isOnScreen;
181
182 Item() : id(0), noun(0), region(0), room(0), picture(0), isShape(false), state(0), description(0), isOnScreen(false) { }
183};
184
185struct Time {
186 byte hours, minutes;
187
188 Time() : hours(12), minutes(0) { }
189};
190
191struct RoomState {
192 byte picture;
193 byte isFirstTime;
194};
195
196struct Region {
199};
200
201struct State {
202 Common::Array<Region> regions;
204 Common::List<Item> items;
206
207 byte region, prevRegion;
208 byte room;
209 byte curPicture;
210 uint16 moves;
211 bool isDark;
212 Time time;
213
214 State() : region(0), prevRegion(0), room(1), curPicture(0), moves(1), isDark(false) { }
215};
216
219
220struct RoomData {
221 Common::String description;
222 PictureMap pictures;
223 Commands commands;
224};
225
226// Opcode debugging macros
227#define OP_DEBUG_0(F) do { \
228 if (DebugMan.isDebugChannelEnabled(kDebugChannelScript) && op_debug(F)) \
229 return 0; \
230} while (0)
231
232#define OP_DEBUG_1(F, P1) do { \
233 if (DebugMan.isDebugChannelEnabled(kDebugChannelScript) && op_debug(F, P1)) \
234 return 1; \
235} while (0)
236
237#define OP_DEBUG_2(F, P1, P2) do { \
238 if (DebugMan.isDebugChannelEnabled(kDebugChannelScript) && op_debug(F, P1, P2)) \
239 return 2; \
240} while (0)
241
242#define OP_DEBUG_3(F, P1, P2, P3) do { \
243 if (DebugMan.isDebugChannelEnabled(kDebugChannelScript) && op_debug(F, P1, P2, P3)) \
244 return 3; \
245} while (0)
246
247#define OP_DEBUG_4(F, P1, P2, P3, P4) do { \
248 if (DebugMan.isDebugChannelEnabled(kDebugChannelScript) && op_debug(F, P1, P2, P3, P4)) \
249 return 4; \
250} while (0)
251
252class AdlEngine : public Engine {
253friend class Console;
254public:
255 ~AdlEngine() override;
256
257 bool pollEvent(Common::Event &event) const;
258 void bell(uint count = 1) const;
259
260protected:
261 AdlEngine(OSystem *syst, const AdlGameDescription *gd);
262
263 // Engine
264 Common::Error loadGameState(int slot) override;
265 Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
266 bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
267 Common::String getSaveStateName(int slot) const override;
268 int getAutosaveSlot() const override { return 15; }
269
270 Common::Path getDiskImageName(byte volume) const { return Adl::getDiskImageName(*_gameDescription, volume); }
271 GameType getGameType() const { return Adl::getGameType(*_gameDescription); }
272 GameVersion getGameVersion() const { return Adl::getGameVersion(*_gameDescription); }
273 Common::Language getLanguage() const { return Adl::getLanguage(*_gameDescription); }
274 virtual void gameLoop();
275 virtual void loadState(Common::ReadStream &stream);
276 virtual void saveState(Common::WriteStream &stream);
277 Common::String readString(Common::ReadStream &stream, byte until = 0, const char *key = "") const;
278 Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const;
279 void extractExeStrings(Common::ReadStream &stream, uint16 printAddr, Common::StringArray &strings) const;
280
281 virtual void printString(const Common::String &str) = 0;
282 virtual Common::String loadMessage(uint idx) const = 0;
283 virtual void printMessage(uint idx);
284 virtual Common::String getItemDescription(const Item &item) const;
285 void delay(uint32 ms) const;
286
287 virtual Common::String getLine();
288 Common::String inputString(byte prompt = 0) const;
289 byte inputKey(bool showCursor = true) const;
290 void waitKey(uint32 ms = 0, Common::KeyCode keycode = Common::KEYCODE_INVALID) const;
291 virtual void getInput(uint &verb, uint &noun);
292 Common::String getWord(const Common::String &line, uint &index) const;
293
294 virtual Common::String formatVerbError(const Common::String &verb) const;
295 virtual Common::String formatNounError(const Common::String &verb, const Common::String &noun) const;
296 void loadWords(Common::ReadStream &stream, WordMap &map, Common::StringArray &pri, uint count = 0) const;
297 void readCommands(Common::ReadStream &stream, Commands &commands);
298 void removeCommand(Commands &commands, uint idx);
299 Command &getCommand(Commands &commands, uint idx);
300 void removeMessage(uint idx);
301 void checkInput(byte verb, byte noun);
302 virtual bool isInputValid(byte verb, byte noun, bool &is_any);
303 virtual bool isInputValid(const Commands &commands, byte verb, byte noun, bool &is_any);
304 virtual void applyRoomWorkarounds(byte roomNr) { }
305 virtual void applyRegionWorkarounds() { }
306
307 virtual void setupOpcodeTables();
308 virtual void initState();
309 virtual void switchRoom(byte roomNr);
310 virtual byte roomArg(byte room) const;
311 virtual void advanceClock() { }
312 void loadDroppedItemOffsets(Common::ReadStream &stream, byte count);
313
314 void stopTextToSpeech() const;
315
316 // Opcodes
318
319 template <class T>
320 Opcode opcode(int (T::*f)(ScriptEnv &)) {
321 return Opcode(new Common::Functor1Mem<ScriptEnv &, int, T>(static_cast<T *>(this), f));
322 }
323
324 virtual int o_isItemInRoom(ScriptEnv &e);
325 virtual int o_isMovesGT(ScriptEnv &e);
326 virtual int o_isVarEQ(ScriptEnv &e);
327 virtual int o_isCurPicEQ(ScriptEnv &e);
328 virtual int o_isItemPicEQ(ScriptEnv &e);
329
330 virtual int o_varAdd(ScriptEnv &e);
331 virtual int o_varSub(ScriptEnv &e);
332 virtual int o_varSet(ScriptEnv &e);
333 virtual int o_listInv(ScriptEnv &e);
334 virtual int o_moveItem(ScriptEnv &e);
335 virtual int o_setRoom(ScriptEnv &e);
336 virtual int o_setCurPic(ScriptEnv &e);
337 virtual int o_setPic(ScriptEnv &e);
338 virtual int o_printMsg(ScriptEnv &e);
339 virtual int o_setLight(ScriptEnv &e);
340 virtual int o_setDark(ScriptEnv &e);
341 virtual int o_save(ScriptEnv &e);
342 virtual int o_restore(ScriptEnv &e);
343 virtual int o_restart(ScriptEnv &e);
344 virtual int o_quit(ScriptEnv &e);
345 virtual int o_placeItem(ScriptEnv &e);
346 virtual int o_setItemPic(ScriptEnv &e);
347 virtual int o_resetPic(ScriptEnv &e);
348 virtual int o_takeItem(ScriptEnv &e);
349 virtual int o_dropItem(ScriptEnv &e);
350 virtual int o_setRoomPic(ScriptEnv &e);
351
352 virtual int goDirection(ScriptEnv &e, Direction D);
353 int o_goNorth(ScriptEnv &e) { return goDirection(e, IDI_DIR_NORTH); }
354 int o_goSouth(ScriptEnv &e) { return goDirection(e, IDI_DIR_SOUTH); }
355 int o_goEast(ScriptEnv &e) { return goDirection(e, IDI_DIR_EAST); }
356 int o_goWest(ScriptEnv &e) { return goDirection(e, IDI_DIR_WEST); }
357 int o_goUp(ScriptEnv &e) { return goDirection(e, IDI_DIR_UP); }
358 int o_goDown(ScriptEnv &e) { return goDirection(e, IDI_DIR_DOWN); }
359
360 // Graphics
361 void drawPic(byte pic, Common::Point pos = Common::Point()) const;
362
363 // Sound
364 bool playTones(const Tones &tones, bool isMusic, bool allowSkip = false) const;
365
366 // Game state functions
367 const Region &getRegion(uint i) const;
368 Region &getRegion(uint i);
369 const Room &getRoom(uint i) const;
370 Room &getRoom(uint i);
371 const Region &getCurRegion() const;
372 Region &getCurRegion();
373 const Room &getCurRoom() const;
374 Room &getCurRoom();
375 const Item &getItem(uint i) const;
376 Item &getItem(uint i);
377 byte getVar(uint i) const;
378 void setVar(uint i, byte value);
379 virtual void takeItem(byte noun);
380 virtual void dropItem(byte noun);
381 bool matchCommand(ScriptEnv &env) const;
382 void doActions(ScriptEnv &env);
383 bool doOneCommand(const Commands &commands, byte verb, byte noun);
384 void doAllCommands(const Commands &commands, byte verb, byte noun);
385 virtual ScriptEnv *createScriptEnv(const Command &cmd, byte room, byte verb, byte noun);
386
387 // Debug functions
388 static Common::String toAscii(const Common::String &str);
389 Common::String itemStr(uint i) const;
390 Common::String roomStr(uint i) const;
391 Common::String itemRoomStr(uint i) const;
392 Common::String verbStr(uint i) const;
393 Common::String nounStr(uint i) const;
394 Common::String msgStr(uint i) const;
395 Common::String dirStr(Direction dir) const;
396 bool op_debug(const char *fmt, ...) const;
397 Common::DumpFile *_dumpFile;
398
399 Display *_display;
400 GraphicsMan *_graphics;
401 bool _textMode;
402
403 // Opcodes
404 Common::Array<Opcode> _condOpcodes, _actOpcodes;
405 // Message strings in data file
407 // Picture data
408 PictureMap _pictures;
409 // Dropped item screen offsets
410 Common::Array<Common::Point> _itemOffsets;
411 // <room, verb, noun, script> lists
412 Commands _roomCommands;
413 Commands _globalCommands;
414 // Data related to the current room
415 RoomData _roomData;
416
417 WordMap _verbs;
418 WordMap _nouns;
419 Common::StringArray _priVerbs;
420 Common::StringArray _priNouns;
421
422 struct {
423 Common::String enterCommand;
424 Common::String verbError;
425 Common::String nounError;
426 Common::String playAgain;
427 Common::String pressReturn;
428 Common::String lineFeeds;
429 } _strings;
430
431 uint32 _verbErrorPos, _nounErrorPos;
432
433 struct {
434 uint cantGoThere;
435 uint dontUnderstand;
436 uint itemDoesntMove;
437 uint itemNotHere;
438 uint thanksForPlaying;
439 } _messageIds;
440
441 // Game state
442 State _state;
443
444 uint _linesPrinted;
445 bool _isRestarting, _isRestoring, _isQuitting;
446 bool _canSaveNow, _canRestoreNow;
447 bool _abortScript;
448 Common::RandomSource *_random;
449
450 const AdlGameDescription *_gameDescription;
451
452 mutable Common::File *_inputScript;
453 mutable uint _scriptDelay;
454 mutable bool _scriptPaused;
455
456private:
457 virtual void runIntro() { }
458 virtual void init() = 0;
459 virtual void initGameState() = 0;
460 virtual void drawItems() = 0;
461 virtual void drawItem(Item &item, const Common::Point &pos) = 0;
462 virtual void loadRoom(byte roomNr) = 0;
463 virtual void showRoom() = 0;
464 virtual void switchRegion(byte region) { }
465 void runScript(const char *filename) const;
466 void stopScript() const;
467 void setScriptDelay(uint scriptDelay) const { _scriptDelay = scriptDelay; }
468 Common::String getScriptLine() const;
469 // Engine
470 Common::Error run() override;
471 bool hasFeature(EngineFeature f) const override;
472 bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
473
474 // Text input
475 byte convertKey(uint16 ascii) const;
476
477 byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
478};
479
480} // End of namespace Adl
481
482#endif
Definition: adl.h:252
Common::String getSaveStateName(int slot) const override
bool canSaveGameStateCurrently(Common::U32String *msg=nullptr) override
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave=false) override
int getAutosaveSlot() const override
Definition: adl.h:268
Common::Error loadGameState(int slot) override
Definition: console.h:39
Definition: adl.h:127
Definition: file.h:145
Definition: error.h:81
Definition: file.h:47
Definition: func.h:452
Definition: list.h:44
Definition: path.h:52
Definition: random.h:44
Definition: stream.h:385
Definition: stream.h:745
Definition: str.h:59
Definition: ustr.h:57
Definition: stream.h:77
Definition: engine.h:149
EngineFeature
Definition: engine.h:282
Definition: system.h:166
Language
Definition: language.h:45
Platform
Definition: platform.h:93
Definition: algorithm.h:29
Definition: detection.h:71
Definition: adl.h:120
Definition: adl.h:169
Definition: adl.h:196
Definition: adl.h:220
Definition: adl.h:99
Definition: adl.h:191
Definition: adl.h:201
Definition: adl.h:185
Definition: events.h:218
Definition: rect.h:144