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