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 #ifndef GNAP_GNAP_H
24 #define GNAP_GNAP_H
25 
26 #include "common/array.h"
27 #include "common/events.h"
28 #include "common/file.h"
29 #include "common/memstream.h"
30 #include "common/random.h"
31 #include "common/savefile.h"
32 #include "common/serializer.h"
33 #include "common/str.h"
34 #include "common/substream.h"
35 #include "common/system.h"
36 #include "engines/engine.h"
37 #include "graphics/pixelformat.h"
38 #include "graphics/fontman.h"
39 #include "graphics/font.h"
40 #include "graphics/fonts/ttf.h"
41 
42 #include "gnap/debugger.h"
43 #include "gnap/resource.h"
44 #include "gnap/scenes/scenecore.h"
45 #include "gnap/character.h"
46 #include "gnap/music.h"
47 
48 struct ADGameDescription;
49 
50 namespace Common {
51 class PEResources;
52 }
53 
54 namespace Gnap {
55 
56 class DatManager;
57 class SequenceResource;
58 class SpriteResource;
59 class GameSys;
60 class SoundMan;
61 class MusicPlayer;
62 
63 #define GNAP_SAVEGAME_VERSION 2
64 
65 struct MouseButtonState {
66 	bool _left;
67 	bool _right;
MouseButtonStateMouseButtonState68 	MouseButtonState() : _left(false), _right(false) {
69 	}
70 };
71 
72 struct Hotspot {
73 	Common::Rect _rect;
74 	uint16 _flags;
75 
isPointInsideHotspot76 	bool isPointInside(Common::Point pos) const {
77 		return _rect.contains(pos);
78 	}
79 
isFlagHotspot80 	bool isFlag(uint16 flag) const {
81 		return (_flags & flag) != 0;
82 	}
83 
clearRectHotspot84 	void clearRect() {
85 		_rect = Common::Rect(0, 0, 0, 0);
86 	}
87 };
88 
89 const int kMaxTimers = 10;
90 
91 enum GnapDebugChannels {
92 	kDebugBasic	= 1 << 0,
93 	kDebugMusic = 1 << 1
94 };
95 
96 enum {
97 	SF_NONE				= 0x0000,
98 	SF_LOOK_CURSOR		= 0x0001,
99 	SF_GRAB_CURSOR		= 0x0002,
100 	SF_TALK_CURSOR		= 0x0004,
101 	SF_PLAT_CURSOR		= 0x0008,
102 	SF_DISABLED			= 0x0010,
103 	SF_WALKABLE			= 0x0020,
104 	SF_EXIT_L_CURSOR	= 0x0040,
105 	SF_EXIT_R_CURSOR	= 0x0080,
106 	SF_EXIT_U_CURSOR	= 0x0100,
107 	SF_EXIT_D_CURSOR	= 0x0200,
108 	SF_EXIT_NW_CURSOR	= 0x0400,
109 	SF_EXIT_NE_CURSOR	= 0x0800,
110 	SF_EXIT_SW_CURSOR	= 0x1000,
111 	SF_EXIT_SE_CURSOR	= 0x2000
112 };
113 
114 enum {
115 	LOOK_CURSOR		= 0,
116 	GRAB_CURSOR		= 1,
117 	TALK_CURSOR		= 2,
118 	PLAT_CURSOR		= 3,
119 	NOLOOK_CURSOR	= 4,
120 	NOGRAB_CURSOR	= 5,
121 	NOTALK_CURSOR	= 6,
122 	NOPLAT_CURSOR	= 7,
123 	EXIT_L_CURSOR	= 8,
124 	EXIT_R_CURSOR	= 9,
125 	EXIT_U_CURSOR	= 10,
126 	EXIT_D_CURSOR	= 11,
127 	EXIT_NE_CURSOR	= 12,
128 	EXIT_NW_CURSOR	= 13,
129 	EXIT_SE_CURSOR	= 14,
130 	EXIT_SW_CURSOR	= 15,
131 	WAIT_CURSOR		= 16
132 };
133 
134 enum {
135 	kGSPullOutDevice			= 0,
136 	kGSPullOutDeviceNonWorking	= 1,
137 	kGSIdle						= 2,
138 	kGSBrainPulsating			= 3,
139 	kGSImpossible				= 4,
140 	kGSScratchingHead			= 5,
141 	kGSDeflect					= 6,
142 	kGSUseDevice				= 7,
143 	kGSMoan1					= 8,
144 	kGSMoan2					= 9
145 };
146 
147 enum {
148 	kItemMagazine			= 0,
149 	kItemMud				= 1,
150 	kItemGrass				= 2,
151 	kItemDisguise			= 3,
152 	kItemNeedle				= 4,
153 	kItemTwig				= 5,
154 	kItemGas				= 6,
155 	kItemKeys				= 7,
156 	kItemDice				= 8,
157 	kItemTongs				= 9,
158 	kItemQuarter			= 10,
159 	kItemQuarterWithHole	= 11,
160 	kItemDiceQuarterHole	= 12,
161 	kItemWrench				= 13,
162 	kItemCowboyHat			= 14,
163 	kItemGroceryStoreHat	= 15,
164 	kItemBanana				= 16,
165 	kItemTickets			= 17,
166 	kItemPicture			= 18,
167 	kItemEmptyBucket		= 19,
168 	kItemBucketWithBeer		= 20,
169 	kItemBucketWithPill		= 21,
170 	kItemPill				= 22,
171 	kItemHorn				= 23,
172 	kItemJoint				= 24,
173 	kItemChickenBucket		= 25,
174 	kItemGum				= 26,
175 	kItemSpring				= 27,
176 	kItemLightbulb			= 28,
177 	kItemCereals			= 29
178 };
179 
180 enum {
181 	kGFPlatypus				= 0,
182 	kGFMudTaken				= 1,
183 	kGFNeedleTaken			= 2,
184 	kGFTwigTaken			= 3,
185 	kGFUnk04				= 4,
186 	kGFKeysTaken			= 5,
187 	kGFGrassTaken			= 6,
188 	kGFBarnPadlockOpen		= 7,
189 	kGFTruckFilledWithGas	= 8,
190 	kGFTruckKeysUsed		= 9,
191 	kGFPlatypusDisguised	= 10,
192 	kGFSceneFlag1			= 11,
193 	kGFGnapControlsToyUFO	= 12,
194 	kGFUnk13				= 13, // Tongue Fight Won?
195 	kGFUnk14				= 14,
196 	kGFSpringTaken			= 15,
197 	kGFUnk16				= 16,
198 	kGFJointTaken			= 17,
199 	kGFUnk18				= 18,
200 	kGFGroceryStoreHatTaken	= 19,
201 	kGFPictureTaken			= 20,
202 	kGFUnk21				= 21,
203 	kGFUnk22				= 22,
204 	kGFUnk23				= 23,
205 	kGFUnk24				= 24,
206 	kGFUnk25				= 25,
207 	kGFPlatypusTalkingToAssistant = 26,
208 	kGFUnk27				= 27,
209 	kGFUnk28				= 28,
210 	kGFGasTaken				= 29,
211 	kGFUnk30				= 30,
212 	kGFUnk31				= 31
213 };
214 
215 struct GnapSavegameHeader {
216 	uint8 _version;
217 	Common::String _saveName;
218 	Graphics::Surface *_thumbnail;
219 	int _year, _month, _day;
220 	int _hour, _minute;
221 };
222 
223 class GnapEngine : public Engine {
224 protected:
225 	Common::Error run() override;
226 	bool hasFeature(EngineFeature f) const override;
227 public:
228 	GnapEngine(OSystem *syst, const ADGameDescription *gd);
229 	~GnapEngine() override;
230 private:
231 	const ADGameDescription *_gameDescription;
232 	Graphics::PixelFormat _pixelFormat;
233 	int _loadGameSlot;
234 
235 public:
236 	Common::RandomSource *_random;
237 	Common::PEResources *_exe;
238 
239 	DatManager *_dat;
240 	SpriteCache *_spriteCache;
241 	SoundCache *_soundCache;
242 	SequenceCache *_sequenceCache;
243 	GameSys *_gameSys;
244 	SoundMan *_soundMan;
245 	Debugger *_debugger;
246 	Scene *_scene;
247 	PlayerGnap *_gnap;
248 	PlayerPlat *_plat;
249 	MusicPlayer *_music;
250 	Graphics::Font *_font;
251 
252 	Common::MemoryWriteStreamDynamic *_tempThumbnail;
253 
254 	int _lastUpdateClock;
255 	bool _gameDone;
256 
257 	bool _keyPressState[512];
258 	bool _keyDownState[512];
259 
260 	bool _isPaused;
261 	Graphics::Surface *_pauseSprite;
262 	int _timers[kMaxTimers], _savedTimers[kMaxTimers];
263 
264 	MouseButtonState _mouseButtonState;
265 	MouseButtonState _mouseClickState;
266 
267 	bool _sceneSavegameLoaded, _wasSavegameLoaded;
268 
269 	Graphics::Surface *_backgroundSurface;
270 	int _prevSceneNum, _currentSceneNum, _newSceneNum;
271 	bool _sceneDone, _sceneWaiting;
272 
273 	uint32 _inventory, _gameFlags;
274 
275 	Hotspot _hotspots[20];
276 	Common::Point _hotspotsWalkPos[20];
277 	int _hotspotsCount;
278 	int _sceneClickedHotspot;
279 
280 	bool _isWaiting;
281 	bool _isLeavingScene;
282 
283 	bool _isStockDatLoaded;
284 
285 	int _newCursorValue, _cursorValue;
286 
287 	int _verbCursor, _cursorIndex;
288 	Common::Point _mousePos;
289 	int _leftClickMouseX, _leftClickMouseY;
290 
291 	Graphics::Surface *_grabCursorSprite;
292 	int _currGrabCursorX, _currGrabCursorY;
293 	int _grabCursorSpriteIndex, _newGrabCursorSpriteIndex;
294 
295 	Graphics::Surface *_fullScreenSprite;
296 	int _fullScreenSpriteId;
297 
298 	int _deviceX1, _deviceY1;
299 
300 	int _soundTimerIndexA;
301 	int _soundTimerIndexB;
302 	int _soundTimerIndexC;
303 	int _idleTimerIndex;
304 
305 	void updateEvents();
306 	void gameUpdateTick();
307 	void saveTimers();
308 	void restoreTimers();
309 
310 	void pauseGame();
311 	void resumeGame();
312 	void updatePause();
313 
314 	int getRandom(int max);
315 
316 	int readSavegameDescription(int savegameNum, Common::String &description);
317 	int loadSavegame(int savegameNum);
318 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
319 	Common::Error loadGameState(int slot) override;
320 	void synchronize(Common::Serializer &s);
321 	void writeSavegameHeader(Common::OutSaveFile *out, GnapSavegameHeader &header);
322 	WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header, bool skipThumbnail = true);
323 
324 	void delayTicks(int val, int idx, bool updateCursor);
325 	void delayTicksA(int val, int idx);
326 	void delayTicksCursor(int val);
327 
328 	void setHotspot(int index, int16 x1, int16 y1, int16 x2, int16 y2, uint16 flags = SF_NONE,
329 		int16 walkX = -1, int16 walkY = -1);
330 	int getHotspotIndexAtPos(Common::Point pos);
331 	void updateCursorByHotspot();
332 	int getClickedHotspotId();
333 
334 	int getInventoryItemSpriteNum(int index);
335 
336 	void updateMouseCursor();
337 	void setVerbCursor(int verbCursor);
338 	void setCursor(int cursorIndex);
339 	void showCursor();
340 	void hideCursor();
341 
342 	void setGrabCursorSprite(int index);
343 	void createGrabCursorSprite(int spriteId);
344 	void freeGrabCursorSprite();
345 	void updateGrabCursorSprite(int x, int y);
346 
347 	void invClear();
348 	void invAdd(int itemId);
349 	void invRemove(int itemId);
350 	bool invHas(int itemId);
351 
352 	void clearFlags();
353 	void setFlag(int num);
354 	void clearFlag(int num);
355 	bool isFlag(int num);
356 
357 	Graphics::Surface *addFullScreenSprite(int resourceId, int id);
358 	void removeFullScreenSprite();
359 	void showFullScreenSprite(int resourceId);
360 
361 	void queueInsertDeviceIcon();
362 	void insertDeviceIconActive();
363 	void removeDeviceIconActive();
364 	void setDeviceHotspot(int hotspotIndex, int x1, int y1, int x2, int y2);
365 
366 	int getSequenceTotalDuration(int resourceId);
367 
368 	bool isSoundPlaying(int resourceId);
369 	void playSound(int resourceId, bool looping);
370 	void stopSound(int resourceId);
371 	void setSoundVolume(int resourceId, int volume);
372 
373 	void updateTimers();
374 
375 	void initGameFlags(int num);
376 	void loadStockDat();
377 
378 	void mainLoop();
379 	void initScene();
380 	void endSceneInit();
381 	void afterScene();
382 
383 	int initSceneLogic();
384 	void runSceneLogic();
385 
386 	void checkGameKeys();
387 
388 	void startSoundTimerA(int timerIndex);
389 	int playSoundA();
390 	void startSoundTimerB(int timerIndex);
391 	int playSoundB();
392 	void startSoundTimerC(int timerIndex);
393 	int playSoundC();
394 	void startIdleTimer(int timerIndex);
395 	void updateIdleTimer();
396 
397 	void screenEffect(int dir, byte r, byte g, byte b);
398 
399 	bool isKeyStatus1(int key);
400 	bool isKeyStatus2(int key);
401 	void clearKeyStatus1(int key);
402 	void clearAllKeyStatus1();
403 
404 	void deleteSurface(Graphics::Surface **surface);
405 
406 	// Menu
407 	int _menuStatus;
408 	int _menuSpritesIndex;
409 	bool _menuDone;
410 	Graphics::Surface *_menuBackgroundSurface;
411 	Graphics::Surface *_menuQuitQuerySprite;
412 	Graphics::Surface *_largeSprite;
413 	Graphics::Surface *_menuSaveLoadSprite;
414 	Graphics::Surface *_menuSprite2;
415 	Graphics::Surface *_menuSprite1;
416 	char _savegameFilenames[7][30];
417 	Graphics::Surface *_savegameSprites[7];
418 	Graphics::Surface *_spriteHandle;
419 	Graphics::Surface *_cursorSprite;
420 	int _menuInventoryIndices[30];
421 	Graphics::Surface *_menuInventorySprites[30];
422 	int _savegameIndex;
423 	void createMenuSprite();
424 	void freeMenuSprite();
425 	void initMenuHotspots1();
426 	void initMenuHotspots2();
427 	void initMenuQuitQueryHotspots();
428 	void initSaveLoadHotspots();
429 	void drawInventoryFrames();
430 	void insertInventorySprites();
431 	void removeInventorySprites();
432 	void runMenu();
433 	void updateMenuStatusInventory();
434 	void updateMenuStatusMainMenu();
435 	void updateMenuStatusSaveGame();
436 	void updateMenuStatusLoadGame();
437 	void updateMenuStatusQueryQuit();
438 
439 	// Grid common
440 	int _gridMinX, _gridMinY;
441 	int _gridMaxX, _gridMaxY;
442 	bool isPointBlocked(int gridX, int gridY);
443 	bool isPointBlocked(Common::Point gridPos);
444 	void initSceneGrid(int gridMinX, int gridMinY, int gridMaxX, int gridMaxY);
445 	bool testWalk(int animationIndex, int someStatus, int gridX1, int gridY1, int gridX2, int gridY2);
446 
447 	// Gnap
448 	void doCallback(int callback);
449 
450 	// Scenes
451 	int _toyUfoNextSequenceId, _toyUfoSequenceId;
452 	int _toyUfoId;
453 	int _toyUfoActionStatus;
454 	int _toyUfoX;
455 	int _toyUfoY;
456 
457 	void initGlobalSceneVars();
458 	void playSequences(int fullScreenSpriteId, int sequenceId1, int sequenceId2, int sequenceId3);
459 
460 	// Shared by scenes 17 & 18
461 	int _s18GarbageCanPos;
462 
463 	// Scene 4x
464 	void toyUfoSetStatus(int flagNum);
465 	int toyUfoGetSequenceId();
466 	bool toyUfoCheckTimer();
467 	void toyUfoFlyTo(int destX, int destY, int minX, int maxX, int minY, int maxY, int animationIndex);
468 
469 	void playMidi(const char *name);
470 	void stopMidi();
471 };
472 
473 } // End of namespace Gnap
474 
475 #endif // GNAP_GNAP_H
476