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 "common/winexe.h"
37 #include "common/winexe_pe.h"
38 #include "engines/engine.h"
39 #include "graphics/pixelformat.h"
40 #include "graphics/wincursor.h"
41 #include "graphics/fontman.h"
42 #include "graphics/font.h"
43 #include "graphics/fonts/ttf.h"
44 
45 #include "gnap/debugger.h"
46 #include "gnap/resource.h"
47 #include "gnap/scenes/scenecore.h"
48 #include "gnap/character.h"
49 #include "gnap/music.h"
50 
51 struct ADGameDescription;
52 
53 namespace Gnap {
54 
55 class DatManager;
56 class SequenceResource;
57 class SpriteResource;
58 class GameSys;
59 class SoundMan;
60 class MusicPlayer;
61 
62 #define GNAP_SAVEGAME_VERSION 2
63 
64 struct MouseButtonState {
65 	bool _left;
66 	bool _right;
MouseButtonStateMouseButtonState67 	MouseButtonState() : _left(false), _right(false) {
68 	}
69 };
70 
71 struct Hotspot {
72 	Common::Rect _rect;
73 	uint16 _flags;
74 
isPointInsideHotspot75 	bool isPointInside(Common::Point pos) const {
76 		return _rect.contains(pos);
77 	}
78 
isFlagHotspot79 	bool isFlag(uint16 flag) const {
80 		return (_flags & flag) != 0;
81 	}
82 
clearRectHotspot83 	void clearRect() {
84 		_rect = Common::Rect(0, 0, 0, 0);
85 	}
86 };
87 
88 const int kMaxTimers = 10;
89 
90 enum GnapDebugChannels {
91 	kDebugBasic	= 1 << 0,
92 	kDebugMusic = 1 << 1
93 };
94 
95 enum {
96 	SF_NONE				= 0x0000,
97 	SF_LOOK_CURSOR		= 0x0001,
98 	SF_GRAB_CURSOR		= 0x0002,
99 	SF_TALK_CURSOR		= 0x0004,
100 	SF_PLAT_CURSOR		= 0x0008,
101 	SF_DISABLED			= 0x0010,
102 	SF_WALKABLE			= 0x0020,
103 	SF_EXIT_L_CURSOR	= 0x0040,
104 	SF_EXIT_R_CURSOR	= 0x0080,
105 	SF_EXIT_U_CURSOR	= 0x0100,
106 	SF_EXIT_D_CURSOR	= 0x0200,
107 	SF_EXIT_NW_CURSOR	= 0x0400,
108 	SF_EXIT_NE_CURSOR	= 0x0800,
109 	SF_EXIT_SW_CURSOR	= 0x1000,
110 	SF_EXIT_SE_CURSOR	= 0x2000
111 };
112 
113 enum {
114 	LOOK_CURSOR		= 0,
115 	GRAB_CURSOR		= 1,
116 	TALK_CURSOR		= 2,
117 	PLAT_CURSOR		= 3,
118 	NOLOOK_CURSOR	= 4,
119 	NOGRAB_CURSOR	= 5,
120 	NOTALK_CURSOR	= 6,
121 	NOPLAT_CURSOR	= 7,
122 	EXIT_L_CURSOR	= 8,
123 	EXIT_R_CURSOR	= 9,
124 	EXIT_U_CURSOR	= 10,
125 	EXIT_D_CURSOR	= 11,
126 	EXIT_NE_CURSOR	= 12,
127 	EXIT_NW_CURSOR	= 13,
128 	EXIT_SE_CURSOR	= 14,
129 	EXIT_SW_CURSOR	= 15,
130 	WAIT_CURSOR		= 16
131 };
132 
133 enum {
134 	kGSPullOutDevice			= 0,
135 	kGSPullOutDeviceNonWorking	= 1,
136 	kGSIdle						= 2,
137 	kGSBrainPulsating			= 3,
138 	kGSImpossible				= 4,
139 	kGSScratchingHead			= 5,
140 	kGSDeflect					= 6,
141 	kGSUseDevice				= 7,
142 	kGSMoan1					= 8,
143 	kGSMoan2					= 9
144 };
145 
146 enum {
147 	kItemMagazine			= 0,
148 	kItemMud				= 1,
149 	kItemGrass				= 2,
150 	kItemDisguise			= 3,
151 	kItemNeedle				= 4,
152 	kItemTwig				= 5,
153 	kItemGas				= 6,
154 	kItemKeys				= 7,
155 	kItemDice				= 8,
156 	kItemTongs				= 9,
157 	kItemQuarter			= 10,
158 	kItemQuarterWithHole	= 11,
159 	kItemDiceQuarterHole	= 12,
160 	kItemWrench				= 13,
161 	kItemCowboyHat			= 14,
162 	kItemGroceryStoreHat	= 15,
163 	kItemBanana				= 16,
164 	kItemTickets			= 17,
165 	kItemPicture			= 18,
166 	kItemEmptyBucket		= 19,
167 	kItemBucketWithBeer		= 20,
168 	kItemBucketWithPill		= 21,
169 	kItemPill				= 22,
170 	kItemHorn				= 23,
171 	kItemJoint				= 24,
172 	kItemChickenBucket		= 25,
173 	kItemGum				= 26,
174 	kItemSpring				= 27,
175 	kItemLightbulb			= 28,
176 	kItemCereals			= 29
177 };
178 
179 enum {
180 	kGFPlatypus				= 0,
181 	kGFMudTaken				= 1,
182 	kGFNeedleTaken			= 2,
183 	kGFTwigTaken			= 3,
184 	kGFUnk04				= 4,
185 	kGFKeysTaken			= 5,
186 	kGFGrassTaken			= 6,
187 	kGFBarnPadlockOpen		= 7,
188 	kGFTruckFilledWithGas	= 8,
189 	kGFTruckKeysUsed		= 9,
190 	kGFPlatypusDisguised	= 10,
191 	kGFSceneFlag1			= 11,
192 	kGFGnapControlsToyUFO	= 12,
193 	kGFUnk13				= 13, // Tongue Fight Won?
194 	kGFUnk14				= 14,
195 	kGFSpringTaken			= 15,
196 	kGFUnk16				= 16,
197 	kGFJointTaken			= 17,
198 	kGFUnk18				= 18,
199 	kGFGroceryStoreHatTaken	= 19,
200 	kGFPictureTaken			= 20,
201 	kGFUnk21				= 21,
202 	kGFUnk22				= 22,
203 	kGFUnk23				= 23,
204 	kGFUnk24				= 24,
205 	kGFUnk25				= 25,
206 	kGFPlatypusTalkingToAssistant = 26,
207 	kGFUnk27				= 27,
208 	kGFUnk28				= 28,
209 	kGFGasTaken				= 29,
210 	kGFUnk30				= 30,
211 	kGFUnk31				= 31
212 };
213 
214 struct GnapSavegameHeader {
215 	uint8 _version;
216 	Common::String _saveName;
217 	Graphics::Surface *_thumbnail;
218 	int _year, _month, _day;
219 	int _hour, _minute;
220 };
221 
222 class GnapEngine : public Engine {
223 protected:
224 	Common::Error run();
225 	virtual bool hasFeature(EngineFeature f) const;
226 public:
227 	GnapEngine(OSystem *syst, const ADGameDescription *gd);
228 	~GnapEngine();
229 private:
230 	const ADGameDescription *_gameDescription;
231 	Graphics::PixelFormat _pixelFormat;
232 	int _loadGameSlot;
233 
234 public:
235 	Common::RandomSource *_random;
236 	Common::PEResources *_exe;
237 
238 	DatManager *_dat;
239 	SpriteCache *_spriteCache;
240 	SoundCache *_soundCache;
241 	SequenceCache *_sequenceCache;
242 	GameSys *_gameSys;
243 	SoundMan *_soundMan;
244 	Debugger *_debugger;
245 	Scene *_scene;
246 	PlayerGnap *_gnap;
247 	PlayerPlat *_plat;
248 	MusicPlayer *_music;
249 	Graphics::Font *_font;
250 
251 	Common::MemoryWriteStreamDynamic *_tempThumbnail;
252 
253 	int _lastUpdateClock;
254 	bool _gameDone;
255 
256 	bool _keyPressState[512];
257 	bool _keyDownState[512];
258 
259 	bool _isPaused;
260 	Graphics::Surface *_pauseSprite;
261 	int _timers[kMaxTimers], _savedTimers[kMaxTimers];
262 
263 	MouseButtonState _mouseButtonState;
264 	MouseButtonState _mouseClickState;
265 
266 	bool _sceneSavegameLoaded, _wasSavegameLoaded;
267 
268 	Graphics::Surface *_backgroundSurface;
269 	int _prevSceneNum, _currentSceneNum, _newSceneNum;
270 	bool _sceneDone, _sceneWaiting;
271 
272 	uint32 _inventory, _gameFlags;
273 
274 	Hotspot _hotspots[20];
275 	Common::Point _hotspotsWalkPos[20];
276 	int _hotspotsCount;
277 	int _sceneClickedHotspot;
278 
279 	bool _isWaiting;
280 	bool _isLeavingScene;
281 
282 	bool _isStockDatLoaded;
283 
284 	int _newCursorValue, _cursorValue;
285 
286 	int _verbCursor, _cursorIndex;
287 	Common::Point _mousePos;
288 	int _leftClickMouseX, _leftClickMouseY;
289 
290 	Graphics::Surface *_grabCursorSprite;
291 	int _currGrabCursorX, _currGrabCursorY;
292 	int _grabCursorSpriteIndex, _newGrabCursorSpriteIndex;
293 
294 	Graphics::Surface *_fullScreenSprite;
295 	int _fullScreenSpriteId;
296 
297 	int _deviceX1, _deviceY1;
298 
299 	int _soundTimerIndexA;
300 	int _soundTimerIndexB;
301 	int _soundTimerIndexC;
302 	int _idleTimerIndex;
303 
304 	void updateEvents();
305 	void gameUpdateTick();
306 	void saveTimers();
307 	void restoreTimers();
308 
309 	void pauseGame();
310 	void resumeGame();
311 	void updatePause();
312 
313 	int getRandom(int max);
314 
315 	int readSavegameDescription(int savegameNum, Common::String &description);
316 	int loadSavegame(int savegameNum);
317 	Common::Error saveGameState(int slot, const Common::String &desc);
318 	Common::Error loadGameState(int slot);
319 	Common::String generateSaveName(int slot);
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