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  /*
24  * This code is based on Labyrinth of Time code with assistance of
25  *
26  * Copyright (c) 1993 Terra Nova Development
27  * Copyright (c) 2004 The Wyrmkeep Entertainment Co.
28  *
29  */
30 
31 #ifndef LAB_LAB_H
32 #define LAB_LAB_H
33 
34 #include "common/system.h"
35 #include "common/random.h"
36 #include "common/rect.h"
37 #include "common/savefile.h"
38 #include "engines/engine.h"
39 #include "engines/savestate.h"
40 
41 #include "lab/console.h"
42 #include "lab/image.h"
43 #include "lab/labsets.h"
44 #include "lab/detection.h"
45 
46 struct ADGameDescription;
47 
48 namespace Lab {
49 
50 struct MapData;
51 struct Action;
52 struct CloseData;
53 struct Button;
54 struct IntuiMessage;
55 struct InventoryData;
56 struct RoomData;
57 struct Rule;
58 struct TextFont;
59 struct ViewData;
60 
61 class Anim;
62 class DisplayMan;
63 class EventManager;
64 class Interface;
65 class Image;
66 class Music;
67 class Resource;
68 class SpecialLocks;
69 class Utils;
70 
71 struct SaveGameHeader {
72 	byte _version;
73 	SaveStateDescriptor _descr;
74 	uint16 _roomNumber;
75 	uint16 _direction;
76 };
77 
78 typedef Common::List<Button *> ButtonList;
79 
80 struct CrumbData {
81 	uint16 _crumbRoomNum;
82 	uint16 _crumbDirection;
83 };
84 
85 #define MAX_CRUMBS          128
86 
87 typedef Common::List<Rule> RuleList;
88 typedef Common::List<Action> ActionList;
89 typedef Common::List<CloseData> CloseDataList;
90 typedef Common::List<ViewData> ViewDataList;
91 
92 enum Direction {
93 	kDirectionNorth,
94 	kDirectionSouth,
95 	kDirectionEast,
96 	kDirectionWest
97 };
98 
99 enum MainButton {
100 	kButtonNone = -1,
101 	kButtonPickup,
102 	kButtonUse,
103 	kButtonOpen,
104 	kButtonClose,
105 	kButtonLook,
106 	kButtonInventory,
107 	kButtonLeft,
108 	kButtonForward,
109 	kButtonRight,
110 	kButtonMap
111 };
112 
113 enum MessageClass {
114 	kMessageLeftClick,
115 	kMessageRightClick,
116 	kMessageButtonUp,
117 	kMessageRawKey
118 };
119 
120 class LabEngine : public Engine {
121 	friend class Console;
122 
123 private:
124 	bool _isCrumbWaiting;
125 	bool _lastTooLong;
126 	bool _lastPage;
127 	bool _mainDisplay;
128 	bool _noUpdateDiff;
129 	bool _quitLab;
130 
131 	byte *_blankJournal;
132 
133 	int _lastWaitTOFTicks;
134 
135 	uint16 _direction;
136 	uint16 _highPalette[20];
137 	uint16 _journalPage;
138 	uint16 _maxRooms;
139 	uint16 _monitorPage;
140 	uint16 _monitorButtonHeight;
141 
142 	uint32 _extraGameFeatures;
143 
144 	Common::String _journalText;
145 	Common::String _journalTextTitle;
146 	Common::String _nextFileName;
147 	Common::String _newFileName;
148 	Common::String _monitorTextFilename;
149 
150 	const CloseData *_closeDataPtr;
151 	ButtonList _journalButtonList;
152 	ButtonList _mapButtonList;
153 	Image *_imgMap, *_imgRoom, *_imgUpArrowRoom, *_imgDownArrowRoom, *_imgBridge;
154 	Image *_imgHRoom, *_imgVRoom, *_imgMaze, *_imgHugeMaze, *_imgPath;
155 	Image *_imgMapX[4];
156 	InventoryData *_inventory;
157 	MapData *_maps;
158 	Image *_monitorButton;
159 	Image *_journalBackImage;
160 	TextFont *_journalFont;
161 	bool _introPlaying;
162 
163 public:
164 	bool _alternate;
165 	bool _droppingCrumbs;
166 	bool _followingCrumbs;
167 	bool _followCrumbsFast;
168 	bool _isCrumbTurning;
169 	bool _isHiRes;
170 
171 	int _roomNum;
172 
173 	uint16 _highestCondition;
174 	uint16 _manyRooms;
175 	uint16 _numCrumbs;
176 	uint16 _numInv;
177 
178 	uint32 _crumbTimestamp;
179 
180 	Common::String _curFileName;
181 
182 	Anim *_anim;
183 	CrumbData _breadCrumbs[MAX_CRUMBS];
184 	DisplayMan *_graphics;
185 	EventManager *_event;
186 	Interface *_interface;
187 	ButtonList _invButtonList;
188 	ButtonList _moveButtonList;
189 	Image *_invImages[10];
190 	Image *_moveImages[20];
191 	LargeSet *_conditions, *_roomsFound;
192 	Music *_music;
193 	Resource *_resource;
194 	RoomData *_rooms;
195 	TextFont *_msgFont;
196 	SpecialLocks *_specialLocks;
197 	Utils *_utils;
198 
199 public:
200 	LabEngine(OSystem *syst, const ADGameDescription *gameDesc);
201 	~LabEngine() override;
202 
203 	Common::Error run() override;
204 	void go();
205 
206 	const ADGameDescription *_gameDescription;
207 	Common::Platform getPlatform() const;
208 	uint32 getFeatures() const;
209 
210 	bool hasFeature(EngineFeature f) const override;
211 
212 	void changeVolume(int delta);
getDirection()213 	uint16 getDirection() { return _direction; }
214 
215 	/**
216 	 * Returns the current picture name.
217 	 */
218 	Common::String getPictName(bool useClose);
219 	uint16 getQuarters();
220 	void setQuarters(uint16 quarters);
221 	void updateEvents();
222 	void waitTOF();
223 
224 	Common::Error loadGameState(int slot) override;
225 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
226 	bool canLoadGameStateCurrently() override;
227 	bool canSaveGameStateCurrently() override;
228 
isMainDisplay()229 	bool isMainDisplay() const { return _mainDisplay; }
230 
231 private:
232 	/**
233 	 * Checks whether all the conditions in a condition list are met.
234 	 */
235 	bool checkConditions(const Common::Array<int16> &cond);
236 
237 	/**
238 	 * Decrements the current inventory number.
239 	 */
240 	void decIncInv(uint16 *CurInv, bool dec);
241 
242 	/**
243 	 * Processes the action list.
244 	 */
245 	void doActions(const ActionList &actionList);
246 
247 	/**
248 	 * Goes through the rules if an action is taken.
249 	 */
250 	bool doActionRule(Common::Point pos, int16 action, int16 roomNum);
251 
252 	/**
253 	 * Does the work for doActionRule.
254 	 */
255 	bool doActionRuleSub(int16 action, int16 roomNum, const CloseData *closePtr, bool allowDefaults);
256 
257 	/**
258 	 * Handles monitor closeups
259 	 */
260 	void handleMonitorCloseup();
261 
262 	/**
263 	 * Goes through the rules if the user tries to go forward.
264 	 */
265 	bool doGoForward();
266 
267 	/**
268 	 * Does the journal processing.
269 	 */
270 	void doJournal();
271 
272 	/**
273 	 * Goes through the rules if the user tries to go to the main view
274 	 */
275 	bool doMainView();
276 
277 	/**
278 	 * Does the map processing.
279 	 */
280 	void doMap();
281 
282 	/**
283 	 * Does what's necessary for the monitor.
284 	 */
285 	void doMonitor(const Common::String background, const Common::String textfile, bool isinteractive, Common::Rect textRect);
286 
287 	/**
288 	 * Does the things to properly set up the detective notes.
289 	 */
290 	void doNotes();
291 
292 	/**
293 	 * Does the work for doActionRule.
294 	 */
295 	bool doOperateRuleSub(int16 itemNum, int16 roomNum, const CloseData *closePtr, bool allowDefaults);
296 
297 	/**
298 	 * Goes through the rules if the user tries to operate an item on an object.
299 	 */
300 	bool doOperateRule(Common::Point pos, int16 ItemNum);
301 
302 	/**
303 	 * Goes through the rules if the user tries to turn.
304 	 */
305 	bool doTurn(uint16 from, uint16 to);
306 
307 	/**
308 	 * If the user hits the "Use" button; things that can get used on themselves.
309 	 */
310 	bool doUse(uint16 curInv);
311 
312 	/**
313 	 * Does the things to properly set up the old west newspaper.  Assumes that
314 	 * OpenHiRes already called.
315 	 */
316 	void doWestPaper();
317 
318 	/**
319 	 * Draws the current direction to the screen.
320 	 */
321 	void drawDirection(const CloseData *closePtr);
322 
323 	/**
324 	 * Draws the journal from page x.
325 	 */
326 	void drawJournal(uint16 wipenum, bool needFade);
327 
328 	/**
329 	 * Draws the text to the back journal screen to the appropriate Page number
330 	 */
331 	void drawJournalText();
332 
333 	/**
334 	 * Draws the map
335 	 */
336 	void drawMap(uint16 curRoom, uint16 curMsg, uint16 floorNum, bool fadeIn);
337 
338 	/**
339 	 * Draws the text for the monitor.
340 	 */
341 	void drawMonText(const char *text, TextFont *monitorFont, Common::Rect textRect, bool isinteractive);
342 
343 	/**
344 	 * Draws a room map.
345 	 */
346 	void drawRoomMap(uint16 curRoom, bool drawMarkFl);
347 
348 	/**
349 	 * Draws the message for the room.
350 	 */
351 	void drawRoomMessage(uint16 curInv, const CloseData *closePtr);
352 	void drawStaticMessage(byte index);
353 
354 	/**
355 	 * Eats all the available messages.
356 	 */
357 	void eatMessages();
358 
359 	/**
360 	 * Goes through the list of closeups to find a match.
361 	 * @note Known bug here.  If there are two objects that have closeups, and
362 	 * some of the closeups have the same hit boxes, then this returns the first
363 	 * occurrence of the object with the same hit box.
364 	 */
365 	const CloseData *findClosePtrMatch(const CloseData *closePtr, const CloseDataList &list);
366 
367 	/**
368 	 * Checks if a floor has been visited.
369 	 */
370 	bool floorVisited(uint16 floorNum);
371 
372 	/**
373 	 * New code to allow quick(er) return navigation in game.
374 	 */
375 	MainButton followCrumbs();
376 	void freeMapData();
377 	void freeScreens();
378 	bool processEvent(MessageClass tmpClass, uint16 code, uint16 qualifier, Common::Point tmpPos,
379 		uint16 &curInv, IntuiMessage *curMsg, bool &forceDraw, uint16 buttonId, uint16 &actionMode);
380 
381 	/**
382 	 * Gets the current inventory name.
383 	 */
384 	Common::String getInvName(uint16 curInv);
385 
386 	/**
387 	 * Returns the floor to show when the down arrow is pressed
388 	 * @note The original did not show all the visited floors, but we do
389 	 */
390 	uint16 getLowerFloor(uint16 floorNum);
391 
392 	/**
393 	 * Gets an object, if any, from the user's click on the screen.
394 	 */
395 	const CloseData *getObject(Common::Point pos, const CloseData *closePtr);
396 
397 	/**
398 	 * Returns the floor to show when the up arrow is pressed
399 	 * @note The original did not show all the visited floors, but we do
400 	 */
401 	uint16 getUpperFloor(uint16 floorNum);
402 
403 	/**
404 	 * Gets the current ViewDataPointer.
405 	 */
406 	ViewData *getViewData(uint16 roomNum, uint16 direction);
407 
408 	/**
409 	 * Turns the interface off.
410 	 */
411 	void interfaceOff();
412 
413 	/**
414 	 * Turns the interface on.
415 	 */
416 	void interfaceOn();
417 
418 	/**
419 	 * Loads in the data for the journal.
420 	 */
421 	void loadJournalData();
422 
423 	/**
424 	 * Loads in the map data.
425 	 */
426 	void loadMapData();
427 
428 	/**
429 	 * The main game loop.
430 	 */
431 	void mainGameLoop();
432 	void showLab2Teaser();
433 
434 	/**
435 	 * Permanently flips the imagery of a button.
436 	 */
437 	void perFlipButton(uint16 buttonId);
438 
439 	/**
440 	 * process a arrow button movement.
441 	 */
442 	uint16 processArrow(uint16 curDirection, uint16 arrow);
443 
444 	/**
445 	 * Processes user input.
446 	 */
447 	void processJournal();
448 
449 	/**
450 	 * Processes the map.
451 	 */
452 	void processMap(uint16 curRoom);
453 
454 	/**
455 	 * Processes user input.
456 	 */
457 	void processMonitor(const Common::String &ntext, TextFont *monitorFont, bool isInteractive, Common::Rect textRect);
458 
459 	/**
460 	 * Figures out what a room's coordinates should be.
461 	 */
462 	Common::Rect roomCoords(uint16 curRoom);
463 	bool saveRestoreGame();
464 
465 	/**
466 	 * Sets the current close up data.
467 	 */
468 	void setCurrentClose(Common::Point pos, const CloseData **closePtrList, bool useAbsoluteCoords, bool next=false);
469 
470 	/**
471 	 * Takes the currently selected item.
472 	 */
473 	bool takeItem(Common::Point pos);
474 
475 	/**
476 	 * Does the turn page wipe.
477 	 */
478 	void turnPage(bool fromLeft);
479 	bool processKey(IntuiMessage *curMsg, uint32 msgClass, uint16 &qualifier, Common::Point &curPos, uint16 &curInv, bool &forceDraw, uint16 code);
480 	void processMainButton(uint16 &curInv, uint16 &lastInv, uint16 &oldDirection, bool &forceDraw, uint16 buttonId, uint16 &actionMode);
481 	void processAltButton(uint16 &curInv, uint16 &lastInv, uint16 buttonId, uint16 &actionMode);
482 	void performAction(uint16 actionMode, Common::Point curPos, uint16 &curInv);
483 
484 	/**
485 	 * Writes the game out to disk.
486 	 */
487 	bool saveGame(int slot, const Common::String desc);
488 
489 	/**
490 	 * Reads the game from disk.
491 	 */
492 	bool loadGame(int slot);
493 	void writeSaveGameHeader(Common::OutSaveFile *out, const Common::String &saveName);
494 
495 	void handleTrialWarning();
496 };
497 
498 WARN_UNUSED_RESULT bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header, bool skipThumbnail = true);
499 
500 } // End of namespace Lab
501 
502 #endif // LAB_LAB_H
503