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 #include "common/config-manager.h"
24 #include "common/debug-channels.h"
25 #include "common/file.h"
26 #include "common/fs.h"
27 #include "common/textconsole.h"
28 
29 #include "engines/util.h"
30 
31 #include "agos/debugger.h"
32 #include "agos/intern.h"
33 #include "agos/agos.h"
34 #include "agos/midi.h"
35 #include "agos/sound.h"
36 
37 #include "backends/audiocd/audiocd.h"
38 
39 #include "graphics/surface.h"
40 
41 #include "audio/mididrv.h"
42 
43 namespace AGOS {
44 
45 static const GameSpecificSettings simon1_settings = {
46 	"",                                     // base_filename
47 	"",                                     // restore_filename
48 	"",                                     // tbl_filename
49 	"EFFECTS",                              // effects_filename
50 	"SIMON",                                // speech_filename
51 };
52 
53 static const GameSpecificSettings simon2_settings = {
54 	"",                                     // base_filename
55 	"",                                     // restore_filename
56 	"",                                     // tbl_filename
57 	"",                                     // effects_filename
58 	"SIMON2",                               // speech_filename
59 };
60 
61 static const GameSpecificSettings dimp_settings = {
62 	"Gdimp",                                // base_filename
63 	"",                                     // restore_filename
64 	"",                                     // tbl_filename
65 	"",                                     // effects_filename
66 	"MUSIC",                                // speech_filename
67 };
68 
69 static const GameSpecificSettings jumble_settings = {
70 	"Gjumble",                              // base_filename
71 	"",                                     // restore_filename
72 	"",                                     // tbl_filename
73 	"",                                     // effects_filename
74 	"MUSIC",                                // speech_filename
75 };
76 
77 static const GameSpecificSettings puzzle_settings = {
78 	"Gpuzzle",                              // base_filename
79 	"",                                     // restore_filename
80 	"",                                     // tbl_filename
81 	"",                                     // effects_filename
82 	"MUSIC",                                // speech_filename
83 };
84 
85 static const GameSpecificSettings swampy_settings = {
86 	"Gswampy",                              // base_filename
87 	"",                                     // restore_filename
88 	"",                                     // tbl_filename
89 	"",                                     // effects_filename
90 	"MUSIC",                                // speech_filename
91 };
92 
93 #ifdef ENABLE_AGOS2
AGOSEngine_DIMP(OSystem * system,const AGOSGameDescription * gd)94 AGOSEngine_DIMP::AGOSEngine_DIMP(OSystem *system, const AGOSGameDescription *gd)
95 	: AGOSEngine_PuzzlePack(system, gd) {
96 
97 	_iconToggleCount = 0;
98 	_voiceCount = 0;
99 
100 	_lastTickCount = 0;
101 	_startSecondCount = 0;
102 	_tSecondCount = 0;
103 }
104 
AGOSEngine_PuzzlePack(OSystem * system,const AGOSGameDescription * gd)105 AGOSEngine_PuzzlePack::AGOSEngine_PuzzlePack(OSystem *system, const AGOSGameDescription *gd)
106 	: AGOSEngine_Feeble(system, gd) {
107 
108 	_oopsValid = false;
109 	_gameTime = 0;
110 }
111 #endif
112 
AGOSEngine_Simon2(OSystem * system,const AGOSGameDescription * gd)113 AGOSEngine_Simon2::AGOSEngine_Simon2(OSystem *system, const AGOSGameDescription *gd)
114 	: AGOSEngine_Simon1(system, gd) {
115 }
116 
AGOSEngine_Simon1(OSystem * system,const AGOSGameDescription * gd)117 AGOSEngine_Simon1::AGOSEngine_Simon1(OSystem *system, const AGOSGameDescription *gd)
118 	: AGOSEngine_Waxworks(system, gd) {
119 }
120 
AGOSEngine_Waxworks(OSystem * system,const AGOSGameDescription * gd)121 AGOSEngine_Waxworks::AGOSEngine_Waxworks(OSystem *system, const AGOSGameDescription *gd)
122 	: AGOSEngine_Elvira2(system, gd) {
123 
124 	_boxCR = false;
125 	_boxLineCount = 0;
126 	memset(_boxBuffer, 0, sizeof(_boxBuffer));
127 	_boxBufferPtr = _boxBuffer;
128 
129 	_linePtrs[0] = 0;
130 	_linePtrs[1] = 0;
131 	_linePtrs[2] = 0;
132 	_linePtrs[3] = 0;
133 	_linePtrs[4] = 0;
134 	_linePtrs[5] = 0;
135 	memset(_lineCounts, 0, sizeof(_lineCounts));
136 }
137 
AGOSEngine_Elvira2(OSystem * system,const AGOSGameDescription * gd)138 AGOSEngine_Elvira2::AGOSEngine_Elvira2(OSystem *system, const AGOSGameDescription *gd)
139 	: AGOSEngine_Elvira1(system, gd) {
140 }
141 
AGOSEngine_Elvira1(OSystem * system,const AGOSGameDescription * gd)142 AGOSEngine_Elvira1::AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescription *gd)
143 	: AGOSEngine(system, gd) {
144 }
145 
AGOSEngine(OSystem * system,const AGOSGameDescription * gd)146 AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
147 	: Engine(system), _rnd("agos"), _gameDescription(gd) {
148 
149 	DebugMan.addDebugChannel(kDebugOpcode, "opcode", "Opcode debug level");
150 	DebugMan.addDebugChannel(kDebugVGAOpcode, "vga_opcode", "VGA Opcode debug level");
151 	DebugMan.addDebugChannel(kDebugSubroutine, "subroutine", "Subroutine debug level");
152 	DebugMan.addDebugChannel(kDebugVGAScript, "vga_script", "VGA Script debug level");
153 	//Image dumping command disabled as it doesn't work well
154 #if 0
155 	DebugMan.addDebugChannel(kDebugImageDump, "image_dump", "Enable dumping of images to files");
156 #endif
157 	_vcPtr = 0;
158 	_vcGetOutOfCode = 0;
159 	_gameOffsetsPtr = 0;
160 
161 	_debugger = 0;
162 
163 	_gameFile = 0;
164 	_opcode = 0;
165 
166 	_itemMemSize = 0;
167 	_tableMemSize = 0;
168 	_vgaMemSize = 0;
169 
170 	_musicIndexBase = 0;
171 	_soundIndexBase = 0;
172 	_tableIndexBase = 0;
173 	_textIndexBase = 0;
174 
175 	_numMusic = 0;
176 	_numSFX = 0;
177 	_numSpeech = 0;
178 	_numZone = 0;
179 
180 	_numBitArray1 = 0;
181 	_numBitArray2 = 0;
182 	_numBitArray3 = 0;
183 	_numItemStore = 0;
184 	_numTextBoxes = 0;
185 	_numVars = 0;
186 	_numVideoOpcodes = 0;
187 	_vgaBaseDelay = 0;
188 	_vgaPeriod = 0;
189 
190 	_strippedTxtMem = 0;
191 	_textMem = 0;
192 	_textSize = 0;
193 	_stringTabNum = 0;
194 	_stringTabPos = 0;
195 	_stringTabSize = 0;
196 	_stringTabPtr = 0;
197 
198 	_itemArrayPtr = 0;
199 	_itemArraySize = 0;
200 	_itemArrayInited = 0;
201 
202 	_iconFilePtr = 0;
203 
204 	_codePtr = 0;
205 
206 	_localStringtable = 0;
207 	_stringIdLocalMin = 0;
208 	_stringIdLocalMax = 0;
209 
210 	_roomStates = 0;
211 	_numRoomStates = 0;
212 
213 	_menuBase = 0;
214 	_roomsList = 0;
215 	_roomsListPtr = 0;
216 
217 	_xtblList = 0;
218 	_xtablesHeapPtrOrg = 0;
219 	_xtablesHeapCurPosOrg = 0;
220 	_xsubroutineListOrg = 0;
221 
222 	_tblList = 0;
223 	_tablesHeapPtr = 0;
224 	_tablesHeapPtrOrg = 0;
225 	_tablesheapPtrNew = 0;
226 	_tablesHeapSize = 0;
227 	_tablesHeapCurPos = 0;
228 	_tablesHeapCurPosOrg = 0;
229 	_tablesHeapCurPosNew = 0;
230 	_subroutineListOrg = 0;
231 
232 	_subroutineList = 0;
233 
234 	_recursionDepth = 0;
235 
236 	_lastVgaTick = 0;
237 
238 	_marks = 0;
239 	_scanFlag = false;
240 
241 	_scriptVar2 = 0;
242 	_runScriptReturn1 = false;
243 	_skipVgaWait = false;
244 	_noParentNotify = false;
245 	_beardLoaded = false;
246 	_litBoxFlag = false;
247 	_mortalFlag = false;
248 	_displayFlag = 0;
249 	_syncFlag2 = false;
250 	_inCallBack = false;
251 	_cepeFlag = false;
252 	_fastMode = false;
253 
254 	_backFlag = false;
255 
256 	_copyProtection = false;
257 	_pause = false;
258 	_speech = false;
259 	_subtitles = false;
260 
261 	_animatePointer = 0;
262 	_maxCursorWidth = 0;
263 	_maxCursorHeight = 0;
264 	_mouseAnim = 0;
265 	_mouseAnimMax = 0;
266 	_mouseCursor = 0;
267 	_mouseData = 0;
268 	_oldMouseCursor = 0;
269 	_currentMouseCursor = 0;
270 	_currentMouseAnim = 0;
271 	_oldMouseAnimMax = 0;
272 
273 	_vgaVar9 = 0;
274 	_chanceModifier = 0;
275 	_restoreWindow6 = 0;
276 	_scrollX = 0;
277 	_scrollY = 0;
278 	_scrollXMax = 0;
279 	_scrollYMax = 0;
280 	_scrollCount = 0;
281 	_scrollFlag = 0;
282 	_scrollHeight = 0;
283 	_scrollWidth = 0;
284 	_scrollImage = 0;
285 	_boxStarHeight = 0;
286 
287 	_scriptVerb = 0;
288 	_scriptNoun1 = 0;
289 	_scriptNoun2 = 0;
290 	_scriptAdj1 = 0;
291 	_scriptAdj2 = 0;
292 
293 	_curWindow = 0;
294 	_textWindow = 0;
295 
296 	_subjectItem = 0;
297 	_objectItem = 0;
298 	_currentPlayer = 0;
299 
300 	_iOverflow = false;
301 	_nameLocked = false;
302 	_hitAreaObjectItem = 0;
303 	_lastHitArea = 0;
304 	_lastNameOn = 0;
305 	_lastHitArea3 = 0;
306 	_hitAreaSubjectItem = 0;
307 	_currentBox = 0;
308 	_currentBoxNum = 0;
309 	_currentVerbBox = 0;
310 	_lastVerbOn = 0;
311 	_needHitAreaRecalc = 0;
312 	_verbHitArea = 0;
313 	_defaultVerb = 0;
314 	_mouseHideCount = 0;
315 
316 	_dragAccept = false;
317 	_dragEnd = false;
318 	_dragFlag = false;
319 	_dragMode = false;
320 	_dragCount = 0;
321 	_lastClickRem = 0;
322 
323 	_windowNum = 0;
324 
325 	_printCharCurPos = 0;
326 	_printCharMaxPos = 0;
327 	_printCharPixelCount = 0;
328 	_numLettersToPrint = 0;
329 
330 	_clockStopped = 0;
331 	_gameStoppedClock = 0;
332 	_lastTime = 0;
333 	_lastMinute = 0;
334 
335 	_firstTimeStruct = 0;
336 	_pendingDeleteTimeEvent = 0;
337 
338 	_initMouse = 0;
339 	_leftButtonDown = false;
340 	_rightButtonDown = false;
341 	_clickOnly = false;
342 	_oneClick = 0;
343 	_leftClick = 0;
344 	_rightClick = 0;
345 	_noRightClick = false;
346 
347 	_leftButton = 0;
348 	_leftButtonCount = 0;
349 	_leftButtonOld = 0;
350 
351 	_dummyItem1 = new Item();
352 	_dummyItem2 = new Item();
353 	_dummyItem3 = new Item();
354 
355 	_videoLockOut = 0;
356 	_scrollUpHitArea = 0;
357 	_scrollDownHitArea = 0;
358 
359 	_noOverWrite = 0;
360 	_rejectBlock = false;
361 
362 	_fastFadeCount = 0;
363 	_fastFadeInFlag = 0;
364 	_fastFadeOutFlag = 0;
365 	_exitCutscene = 0;
366 	_paletteFlag = 0;
367 	_bottomPalette = false;
368 	_picture8600 = 0;
369 
370 	_soundFileId = 0;
371 	_lastMusicPlayed = 0;
372 	_nextMusicToPlay = 0;
373 	_sampleEnd = 0;
374 	_sampleWait = 0;
375 
376 	_showPreposition = 0;
377 	_showMessageFlag = 0;
378 
379 	_newDirtyClip = false;
380 	_wiped = false;
381 	_copyScnFlag = 0;
382 	_vgaSpriteChanged = 0;
383 
384 	_block = 0;
385 	_blockEnd = 0;
386 	_vgaMemPtr = 0;
387 	_vgaMemEnd = 0;
388 	_vgaMemBase = 0;
389 	_vgaFrozenBase = 0;
390 	_vgaRealBase = 0;
391 	_zoneBuffers = 0;
392 
393 	_curVgaFile1 = 0;
394 	_curVgaFile2 = 0;
395 	_curSfxFile = 0;
396 	_curSfxFileSize = 0;
397 
398 	_syncCount = 0;
399 
400 	_frameCount = 0;
401 
402 	_zoneNumber = 0;
403 
404 	_vgaWaitFor = 0;
405 	_lastVgaWaitFor = 0;
406 
407 	_vgaCurZoneNum = 0;
408 	_vgaCurSpriteId = 0;
409 
410 	_baseY = 0;
411 	_scale = 0;
412 
413 	_feebleRect.left = 0;
414 	_feebleRect.right = 0;
415 	_feebleRect.top = 0;
416 	_feebleRect.bottom = 0;
417 
418 	_scaleX = 0;
419 	_scaleY = 0;
420 	_scaleWidth = 0;
421 	_scaleHeight = 0;
422 
423 	_nextVgaTimerToProcess = 0;
424 
425 	_opcode177Var1 = 1;
426 	_opcode177Var2 = 0;
427 	_opcode178Var1 = 1;
428 	_opcode178Var2 = 0;
429 
430 	_classLine = 0;
431 	_classMask = 0;
432 	_classMode1 = 0;
433 	_classMode2 = 0;
434 	_currentLine = 0;
435 	_currentTable = 0;
436 	_findNextPtr = 0;
437 
438 	_agosMenu = 0;
439 	_currentRoom = 0;
440 	_superRoomNumber = 0;
441 	_wallOn = 0;
442 
443 	memset(_objectArray, 0, sizeof(_objectArray));
444 	memset(_itemStore, 0, sizeof(_itemStore));
445 	memset(_textMenu, 0, sizeof(_textMenu));
446 
447 	memset(_shortText, 0, sizeof(_shortText));
448 	memset(_shortTextX, 0, sizeof(_shortText));
449 	memset(_shortTextY, 0, sizeof(_shortText));
450 	memset(_longText, 0, sizeof(_longText));
451 	memset(_longSound, 0, sizeof(_longSound));
452 
453 	memset(_bitArray, 0, sizeof(_bitArray));
454 	memset(_bitArrayTwo, 0, sizeof(_bitArrayTwo));
455 	memset(_bitArrayThree, 0, sizeof(_bitArrayThree));
456 
457 	_variableArray = 0;
458 	_variableArray2 = 0;
459 	_variableArrayPtr = 0;
460 
461 	memset(_windowArray, 0, sizeof(_windowArray));
462 
463 	memset(_fcsData1, 0, sizeof(_fcsData1));
464 	memset(_fcsData2, 0, sizeof(_fcsData2));
465 
466 	_awaitTwoByteToken = 0;
467 	_byteTokens = 0;
468 	_byteTokenStrings = 0;
469 	_twoByteTokens = 0;
470 	_twoByteTokenStrings = 0;
471 	_secondTwoByteTokenStrings = 0;
472 	_thirdTwoByteTokenStrings = 0;
473 	memset(_textBuffer, 0, sizeof(_textBuffer));
474 	_textCount = 0;
475 
476 	_freeStringSlot = 0;
477 
478 	memset(_stringReturnBuffer, 0, sizeof(_stringReturnBuffer));
479 
480 	memset(_pathFindArray, 0, sizeof(_pathFindArray));
481 
482 	memset(_pathValues, 0, sizeof(_pathValues));
483 	_PVCount = 0;
484 	_GPVCount = 0;
485 
486 	memset(_pathValues1, 0, sizeof(_pathValues1));
487 	_PVCount1 = 0;
488 	_GPVCount1 = 0;
489 
490 	memset(_currentPalette, 0, sizeof(_currentPalette));
491 	memset(_displayPalette, 0, sizeof(_displayPalette));
492 
493 	memset(_videoBuf1, 0, sizeof(_videoBuf1));
494 	memset(_videoWindows, 0, sizeof(_videoWindows));
495 
496 	_dummyWindow = new WindowBlock;
497 	_windowList = new WindowBlock[16];
498 
499 	memset(_lettersToPrintBuf, 0, sizeof(_lettersToPrintBuf));
500 
501 	_planarBuf = 0;
502 
503 	_midiEnabled = false;
504 
505 	_vgaTickCounter = 0;
506 
507 	_sound = 0;
508 
509 	_effectsPaused = false;
510 	_ambientPaused = false;
511 	_musicPaused = false;
512 
513 	_saveLoadType = 0;
514 	_saveLoadSlot = 0;
515 	memset(_saveLoadName, 0, sizeof(_saveLoadName));
516 	memset(_saveBuf, 0, sizeof(_saveBuf));
517 
518 	_saveGameNameLen = 0;
519 	_saveLoadRowCurPos = 0;
520 	_numSaveGameRows = 0;
521 	_saveDialogFlag = false;
522 	_saveOrLoad = false;
523 	_saveLoadEdit = false;
524 
525 	_hyperLink = 0;
526 	_interactY = 0;
527 	_oracleMaxScrollY = 0;
528 	_noOracleScroll = 0;
529 
530 	_backGroundBuf = 0;
531 	_backBuf = 0;
532 	_scaleBuf = 0;
533 	_window4BackScn = 0;
534 	_window6BackScn = 0;
535 
536 	_window3Flag = 0;
537 	_window4Flag = 0;
538 	_window6Flag = 0;
539 
540 	_moveXMin = 0;
541 	_moveYMin = 0;
542 	_moveXMax = 0;
543 	_moveYMax = 0;
544 
545 	_vc10BasePtrOld = 0;
546 	memcpy (_hebrewCharWidths,
547 		"\x5\x5\x4\x6\x5\x3\x4\x5\x6\x3\x5\x5\x4\x6\x5\x3\x4\x6\x5\x6\x6\x6\x5\x5\x5\x6\x5\x6\x6\x6\x6\x6", 32);
548 
549 
550 	const Common::FSNode gameDataDir(ConfMan.get("path"));
551 
552 	// Add default file directories for Acorn version of
553 	// Simon the Sorcerer 1
554 	SearchMan.addSubDirectoryMatching(gameDataDir, "execute");
555 
556 	// Add default file directories for Amiga/Macintosh
557 	// versions of Simon the Sorcerer 2
558 	SearchMan.addSubDirectoryMatching(gameDataDir, "voices");
559 
560 	// Add default file directories for Amiga & Macintosh
561 	// versions of The Feeble Files
562 	SearchMan.addSubDirectoryMatching(gameDataDir, "gfx");
563 	SearchMan.addSubDirectoryMatching(gameDataDir, "movies");
564 	SearchMan.addSubDirectoryMatching(gameDataDir, "sfx");
565 	SearchMan.addSubDirectoryMatching(gameDataDir, "speech");
566 }
567 
init()568 Common::Error AGOSEngine::init() {
569 	if (getGameId() == GID_DIMP) {
570 		_screenWidth = 496;
571 		_screenHeight = 400;
572 	} else if (getGameType() == GType_FF || getGameType() == GType_PP) {
573 		_screenWidth = 640;
574 		_screenHeight = 480;
575 	} else {
576 		_screenWidth = 320;
577 		_screenHeight = 200;
578 	}
579 
580 	initGraphics(_screenWidth, _screenHeight);
581 
582 	_midi = new MidiPlayer();
583 
584 	if ((getGameType() == GType_SIMON2 && getPlatform() == Common::kPlatformWindows) ||
585 		(getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformWindows) ||
586 		((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) ||
587 		(getPlatform() == Common::kPlatformDOS)) {
588 
589 		bool isDemo = (getFeatures() & GF_DEMO) ? true : false;
590 
591 		int ret = _midi->open(getGameType(), isDemo);
592 		if (ret)
593 			warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName(ret));
594 
595 		_midi->setVolume(ConfMan.getInt("music_volume"), ConfMan.getInt("sfx_volume"));
596 
597 		_midiEnabled = true;
598 	}
599 
600 	// Setup mixer
601 	syncSoundSettings();
602 
603 	// allocate buffers
604 	_backGroundBuf = new Graphics::Surface();
605 	_backGroundBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
606 
607 	if (getGameType() == GType_FF || getGameType() == GType_PP) {
608 		_backBuf = new Graphics::Surface();
609 		_backBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
610 		_scaleBuf = new Graphics::Surface();
611 		_scaleBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
612 	}
613 
614 	if (getGameType() == GType_SIMON2) {
615 		_window4BackScn = new Graphics::Surface();
616 		_window4BackScn->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
617 	} else if (getGameType() == GType_SIMON1) {
618 		_window4BackScn = new Graphics::Surface();
619 		_window4BackScn->create(_screenWidth, 134, Graphics::PixelFormat::createFormatCLUT8());
620 	} else if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2) {
621 		_window4BackScn = new Graphics::Surface();
622 		_window4BackScn->create(224, 127, Graphics::PixelFormat::createFormatCLUT8());
623 	} else if (getGameType() == GType_ELVIRA1) {
624 		_window4BackScn = new Graphics::Surface();
625 		if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_DEMO)) {
626 			_window4BackScn->create(224, 196, Graphics::PixelFormat::createFormatCLUT8());
627 		} else {
628 			_window4BackScn->create(224, 144, Graphics::PixelFormat::createFormatCLUT8());
629 		}
630 		_window6BackScn = new Graphics::Surface();
631 		_window6BackScn->create(48, 80, Graphics::PixelFormat::createFormatCLUT8());
632 	}
633 
634 	setupGame();
635 
636 	_debugger = new Debugger(this);
637 	_sound = new Sound(this, gss, _mixer);
638 
639 	if (ConfMan.hasKey("music_mute") && ConfMan.getBool("music_mute") == 1) {
640 		_musicPaused = true;
641 		if (_midiEnabled) {
642 			_midi->pause(_musicPaused);
643 		}
644 		_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, 0);
645 	}
646 
647 	if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) {
648 		if (getGameId() == GID_SIMON1DOS)
649 			_midi->_enable_sfx = !_midi->_enable_sfx;
650 		else {
651 			_effectsPaused = !_effectsPaused;
652 			_sound->effectsPause(_effectsPaused);
653 		}
654 	}
655 
656 	_copyProtection = ConfMan.getBool("copy_protection");
657 	_language = Common::parseLanguage(ConfMan.get("language"));
658 
659 	if (getGameType() == GType_PP) {
660 		_speech = true;
661 		_subtitles = false;
662 	} else if (getFeatures() & GF_TALKIE) {
663 		_speech = !ConfMan.getBool("speech_mute");
664 		_subtitles = ConfMan.getBool("subtitles");
665 
666 		if (getGameType() == GType_SIMON1) {
667 			// English and German versions don't have full subtitles
668 			if (_language == Common::EN_ANY || _language == Common::DE_DEU)
669 				_subtitles = false;
670 			// Other versions require speech to be enabled
671 			else
672 				_speech = true;
673 		}
674 
675 		// Default to speech only, if both speech and subtitles disabled
676 		if (!_speech && !_subtitles)
677 			_speech = true;
678 	} else {
679 		_speech = false;
680 		_subtitles = true;
681 	}
682 
683 	return Common::kNoError;
684 }
685 
686 static const uint16 initialVideoWindows_Simon[20] = {
687 	0,  0, 20, 200,
688 	0,  0,  3, 136,
689 	17, 0,  3, 136,
690 	0,  0, 20, 200,
691 	0,  0, 20, 134
692 };
693 
694 static const uint16 initialVideoWindows_Common[20] = {
695 	 3, 0, 14, 136,
696 	 0, 0,  3, 136,
697 	17, 0,  3, 136,
698 	 0, 0, 20, 200,
699 	 3, 3, 14, 127,
700 };
701 
702 static const uint16 initialVideoWindows_PN[20] = {
703 	 3, 0, 14, 136,
704 	 0, 0,  3, 136,
705 	17, 0,  3, 136,
706 	 0, 0, 20, 200,
707 	 3, 2, 14, 129,
708 };
709 
710 #ifdef ENABLE_AGOS2
setupGame()711 void AGOSEngine_PuzzlePack::setupGame() {
712 	if (getGameId() == GID_DIMP) {
713 		gss = &dimp_settings;
714 	} else if (getGameId() == GID_JUMBLE) {
715 		gss = &jumble_settings;
716 	} else if (getGameId() == GID_PUZZLE) {
717 		gss = &puzzle_settings;
718 	} else if (getGameId() == GID_SWAMPY) {
719 		gss = &swampy_settings;
720 	}
721 	_numVideoOpcodes = 85;
722 	_vgaMemSize = 7500000;
723 	_itemMemSize = 20000;
724 	_tableMemSize = 200000;
725 	_frameCount = 1;
726 	_vgaBaseDelay = 5;
727 	_vgaPeriod = (getGameId() == GID_DIMP) ? 35 : 30;
728 	_numBitArray1 = 128;
729 	_numItemStore = 10;
730 	_numTextBoxes = 40;
731 	_numVars = 2048;
732 
733 	_numZone = 450;
734 
735 	AGOSEngine::setupGame();
736 }
737 #endif
738 
setupGame()739 void AGOSEngine_Simon2::setupGame() {
740 	gss = &simon2_settings;
741 	_tableIndexBase = 1580 / 4;
742 	_textIndexBase = 1500 / 4;
743 	_numVideoOpcodes = 75;
744 #if defined(__DS__)
745 	_vgaMemSize = 1300000;
746 #else
747 	_vgaMemSize = 2000000;
748 #endif
749 	_itemMemSize = 20000;
750 	_tableMemSize = 100000;
751 	// Check whether to use MT-32 MIDI tracks in Simon the Sorcerer 2
752 	if (getGameType() == GType_SIMON2 && _midi->hasNativeMT32())
753 		_musicIndexBase = (1128 + 612) / 4;
754 	else
755 		_musicIndexBase = 1128 / 4;
756 	_soundIndexBase = 1660 / 4;
757 	_frameCount = 1;
758 	_vgaBaseDelay = 1;
759 	_vgaPeriod = 45;
760 	_numBitArray1 = 16;
761 	_numBitArray2 = 16;
762 	_numItemStore = 10;
763 	_numTextBoxes = 20;
764 	_numVars = 255;
765 
766 	_numMusic = 93;
767 	_numSFX = 222;
768 	_numSpeech = 11997;
769 	_numZone = 140;
770 
771 	AGOSEngine::setupGame();
772 }
773 
setupGame()774 void AGOSEngine_Simon1::setupGame() {
775 	gss = &simon1_settings;
776 	_tableIndexBase = 1576 / 4;
777 	_textIndexBase = 1460 / 4;
778 	_numVideoOpcodes = 64;
779 	_vgaMemSize = 1000000;
780 	_itemMemSize = 20000;
781 	_tableMemSize = 50000;
782 	_musicIndexBase = 1316 / 4;
783 	_soundIndexBase = 0;
784 	_frameCount = 1;
785 	_vgaBaseDelay = 1;
786 	_vgaPeriod = 50;
787 	_numBitArray1 = 16;
788 	_numBitArray2 = 16;
789 	_numItemStore = 10;
790 	_numTextBoxes = 20;
791 	_numVars = 255;
792 
793 	_numMusic = 34;
794 	_numSFX = 127;
795 	_numSpeech = 3623;
796 	_numZone = 164;
797 
798 	AGOSEngine::setupGame();
799 }
800 
setupGame()801 void AGOSEngine_Waxworks::setupGame() {
802 	gss = &simon1_settings;
803 	_numVideoOpcodes = 64;
804 	_vgaMemSize = 1000000;
805 	_itemMemSize = 80000;
806 	_tableMemSize = 50000;
807 	_frameCount = 4;
808 	_vgaBaseDelay = 1;
809 	_vgaPeriod = 50;
810 	_numBitArray1 = 16;
811 	_numBitArray2 = 15;
812 	_numItemStore = 50;
813 	_numTextBoxes = 10;
814 	_numVars = 255;
815 
816 	_numMusic = 26;
817 	_numZone = 155;
818 
819 	AGOSEngine::setupGame();
820 }
821 
setupGame()822 void AGOSEngine_Elvira2::setupGame() {
823 	gss = &simon1_settings;
824 	_numVideoOpcodes = 60;
825 	_vgaMemSize = 1000000;
826 	_itemMemSize = 64000;
827 	_tableMemSize = 100000;
828 	_frameCount = 4;
829 	_vgaBaseDelay = 1;
830 	_vgaPeriod = 50;
831 	_numBitArray1 = 16;
832 	_numBitArray2 = 15;
833 	_numItemStore = 50;
834 	_numVars = 255;
835 
836 	_numMusic = 9;
837 	_numZone = 99;
838 
839 	AGOSEngine::setupGame();
840 }
841 
setupGame()842 void AGOSEngine_Elvira1::setupGame() {
843 	gss = &simon1_settings;
844 	_numVideoOpcodes = 57;
845 	_vgaMemSize = 1000000;
846 	_itemMemSize = 64000;
847 	_tableMemSize = 256000;
848 	_frameCount = 4;
849 	_vgaBaseDelay = 1;
850 	_vgaPeriod = 50;
851 	_numVars = 512;
852 
853 	_numMusic = 14;
854 	_numZone = 74;
855 
856 	AGOSEngine::setupGame();
857 }
858 
setupGame()859 void AGOSEngine_PN::setupGame() {
860 	gss = &simon1_settings;
861 	_numVideoOpcodes = 57;
862 	_vgaMemSize = 1000000;
863 	_frameCount = 4;
864 	_vgaBaseDelay = 1;
865 	_vgaPeriod = 50;
866 	_numVars = 256;
867 
868 	_numZone = 26;
869 
870 	AGOSEngine::setupGame();
871 }
872 
setupGame()873 void AGOSEngine::setupGame() {
874 	allocItemHeap();
875 	allocTablesHeap();
876 
877 	if (getGameType() != GType_SIMON2)
878 		initMouse();
879 
880 	_variableArray = (int16 *)calloc(_numVars, sizeof(int16));
881 	_variableArrayPtr = _variableArray;
882 	if (getGameType() == GType_FF || getGameType() == GType_PP) {
883 		_variableArray2 = (int16 *)calloc(_numVars, sizeof(int16));
884 	}
885 
886 	setupOpcodes();
887 	setupVgaOpcodes();
888 
889 	setZoneBuffers();
890 
891 	_currentMouseCursor = 255;
892 	_currentMouseAnim = 255;
893 
894 	_lastMusicPlayed = -1;
895 	_nextMusicToPlay = -1;
896 
897 	_noOverWrite = 0xFFFF;
898 
899 	_stringIdLocalMin = 1;
900 
901 	_agosMenu = 1;
902 	_superRoomNumber = 1;
903 
904 	for (int i = 0; i < 20; i++) {
905 		if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
906 			_videoWindows[i] = initialVideoWindows_Simon[i];
907 		} else if (getGameType() == GType_PN) {
908 			_videoWindows[i] = initialVideoWindows_PN[i];
909 		} else {
910 			_videoWindows[i] = initialVideoWindows_Common[i];
911 		}
912 	}
913 
914 	if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST) {
915 		_videoWindows[9] = 75;
916 	}
917 }
918 
~AGOSEngine()919 AGOSEngine::~AGOSEngine() {
920 	_system->getAudioCDManager()->stop();
921 
922 	for (uint i = 0; i < _itemHeap.size(); i++) {
923 		delete[] _itemHeap[i];
924 	}
925 	_itemHeap.clear();
926 
927 	free(_tablesHeapPtr - _tablesHeapCurPos);
928 
929 	free(_mouseData);
930 
931 	free(_gameOffsetsPtr);
932 	free(_iconFilePtr);
933 	free(_itemArrayPtr);
934 	free(_menuBase);
935 	free(_roomsList);
936 	free(_roomStates);
937 	free(_stringTabPtr);
938 	free(_strippedTxtMem);
939 	free(_tblList);
940 	free(_textMem);
941 	free(_xtblList);
942 
943 	if (_backGroundBuf)
944 		_backGroundBuf->free();
945 	delete _backGroundBuf;
946 	if (_backBuf)
947 		_backBuf->free();
948 	delete _backBuf;
949 	free(_planarBuf);
950 	if (_scaleBuf)
951 		_scaleBuf->free();
952 	delete _scaleBuf;
953 	free(_zoneBuffers);
954 
955 	if (_window4BackScn)
956 		_window4BackScn->free();
957 	delete _window4BackScn;
958 	if (_window6BackScn)
959 		_window6BackScn->free();
960 	delete _window6BackScn;
961 
962 	delete _midi;
963 
964 	free(_firstTimeStruct);
965 	free(_pendingDeleteTimeEvent);
966 
967 	free(_variableArray);
968 	free(_variableArray2);
969 
970 	delete _dummyItem1;
971 	delete _dummyItem2;
972 	delete _dummyItem3;
973 
974 	delete _dummyWindow;
975 	delete[] _windowList;
976 
977 	delete _debugger;
978 	delete _sound;
979 	delete _gameFile;
980 }
981 
getDebugger()982 GUI::Debugger *AGOSEngine::getDebugger() {
983 	return _debugger;
984 }
985 
pauseEngineIntern(bool pauseIt)986 void AGOSEngine::pauseEngineIntern(bool pauseIt) {
987 	if (pauseIt) {
988 		_keyPressed.reset();
989 		_pause = true;
990 
991 		_midi->pause(true);
992 		_mixer->pauseAll(true);
993 	} else {
994 		_pause = false;
995 
996 		_midi->pause(_musicPaused);
997 		_mixer->pauseAll(false);
998 	}
999 }
1000 
pause()1001 void AGOSEngine::pause() {
1002 	pauseEngine(true);
1003 
1004 	while (_pause && !shouldQuit()) {
1005 		delay(1);
1006 		if (_keyPressed.keycode == Common::KEYCODE_PAUSE) {
1007 			pauseEngine(false);
1008 			_keyPressed.reset();
1009 		}
1010 	}
1011 }
1012 
go()1013 Common::Error AGOSEngine::go() {
1014 #ifdef ENABLE_AGOS2
1015 	loadArchives();
1016 #endif
1017 
1018 	loadGamePcFile();
1019 
1020 	addTimeEvent(0, 1);
1021 
1022 	if (getFileName(GAME_GMEFILE) != NULL) {
1023 		openGameFile();
1024 	}
1025 
1026 	if (getGameType() == GType_FF) {
1027 		loadIconData();
1028 	} else if (getFileName(GAME_ICONFILE) != NULL) {
1029 		loadIconFile();
1030 	}
1031 
1032 	if (getFileName(GAME_MENUFILE) != NULL) {
1033 		loadMenuFile();
1034 	}
1035 
1036 	vc34_setMouseOff();
1037 
1038 	if (getGameType() != GType_PP && getGameType() != GType_FF) {
1039 		uint16 count = (getGameType() == GType_SIMON2) ? 5 : _frameCount;
1040 		addVgaEvent(count, ANIMATE_INT, NULL, 0, 0);
1041 	}
1042 
1043 	if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformAtariST &&
1044 		(getFeatures() & GF_DEMO)) {
1045 		setWindowImage(3, 9900);
1046 		while (!shouldQuit())
1047 			delay(0);
1048 	}
1049 
1050 	if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformAmiga &&
1051 		(getFeatures() & GF_DEMO)) {
1052 		playMusic(0, 0);
1053 	}
1054 
1055 	runSubroutine101();
1056 	permitInput();
1057 
1058 	while (!shouldQuit()) {
1059 		waitForInput();
1060 		handleVerbClicked(_verbHitArea);
1061 		delay(100);
1062 	}
1063 
1064 	return Common::kNoError;
1065 }
1066 
1067 
getTime() const1068 uint32 AGOSEngine::getTime() const {
1069 	return _system->getMillis() / 1000;
1070 }
1071 
syncSoundSettings()1072 void AGOSEngine::syncSoundSettings() {
1073 	Engine::syncSoundSettings();
1074 
1075 	bool mute = false;
1076 	if (ConfMan.hasKey("mute"))
1077 		mute = ConfMan.getBool("mute");
1078 
1079 	// Sync the engine with the config manager
1080 	int soundVolumeMusic = ConfMan.getInt("music_volume");
1081 	int soundVolumeSFX = ConfMan.getInt("sfx_volume");
1082 
1083 	if (_midiEnabled)
1084 		_midi->setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX));
1085 }
1086 
1087 } // End of namespace AGOS
1088