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 "mohawk/console.h"
24 #include "mohawk/cursors.h"
25 #include "mohawk/livingbooks.h"
26 #include "mohawk/resource.h"
27 #include "mohawk/sound.h"
28 #include "mohawk/video.h"
29 
30 #include "common/system.h"
31 #include "common/textconsole.h"
32 
33 #ifdef ENABLE_CSTIME
34 #include "mohawk/cstime.h"
35 #endif
36 
37 #ifdef ENABLE_MYST
38 #include "mohawk/myst.h"
39 #include "mohawk/myst_areas.h"
40 #include "mohawk/myst_card.h"
41 #include "mohawk/myst_graphics.h"
42 #include "mohawk/myst_scripts.h"
43 #include "mohawk/myst_sound.h"
44 #endif
45 
46 #ifdef ENABLE_RIVEN
47 #include "mohawk/riven.h"
48 #include "mohawk/riven_card.h"
49 #include "mohawk/riven_sound.h"
50 #include "mohawk/riven_stack.h"
51 #include "mohawk/riven_stacks/domespit.h"
52 #endif
53 
54 namespace Mohawk {
55 
56 #ifdef ENABLE_MYST
57 
MystConsole(MohawkEngine_Myst * vm)58 MystConsole::MystConsole(MohawkEngine_Myst *vm) : GUI::Debugger(), _vm(vm) {
59 	registerCmd("changeCard",			WRAP_METHOD(MystConsole, Cmd_ChangeCard));
60 	registerCmd("curCard",			WRAP_METHOD(MystConsole, Cmd_CurCard));
61 	registerCmd("var",				WRAP_METHOD(MystConsole, Cmd_Var));
62 	registerCmd("curStack",			WRAP_METHOD(MystConsole, Cmd_CurStack));
63 	registerCmd("changeStack",		WRAP_METHOD(MystConsole, Cmd_ChangeStack));
64 	registerCmd("drawImage",			WRAP_METHOD(MystConsole, Cmd_DrawImage));
65 	registerCmd("drawRect",			WRAP_METHOD(MystConsole, Cmd_DrawRect));
66 	registerCmd("setResourceEnable",	WRAP_METHOD(MystConsole, Cmd_SetResourceEnable));
67 	registerCmd("playSound",			WRAP_METHOD(MystConsole, Cmd_PlaySound));
68 	registerCmd("stopSound",			WRAP_METHOD(MystConsole, Cmd_StopSound));
69 	registerCmd("playMovie",			WRAP_METHOD(MystConsole, Cmd_PlayMovie));
70 	registerCmd("disableInitOpcodes",	WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes));
71 	registerCmd("cache",				WRAP_METHOD(MystConsole, Cmd_Cache));
72 	registerCmd("resources",			WRAP_METHOD(MystConsole, Cmd_Resources));
73 	registerCmd("quickTest",            WRAP_METHOD(MystConsole, Cmd_QuickTest));
74 	registerVar("show_resource_rects",  &_vm->_showResourceRects);
75 }
76 
~MystConsole()77 MystConsole::~MystConsole() {
78 }
79 
Cmd_ChangeCard(int argc,const char ** argv)80 bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) {
81 	if (argc < 2) {
82 		debugPrintf("Usage: changeCard <card>\n");
83 		return true;
84 	}
85 
86 	_vm->_sound->stopEffect();
87 	_vm->changeToCard((uint16)atoi(argv[1]), kTransitionCopy);
88 
89 	return false;
90 }
91 
Cmd_CurCard(int argc,const char ** argv)92 bool MystConsole::Cmd_CurCard(int argc, const char **argv) {
93 	debugPrintf("Current Card: %d\n", _vm->getCard()->getId());
94 	return true;
95 }
96 
Cmd_Var(int argc,const char ** argv)97 bool MystConsole::Cmd_Var(int argc, const char **argv) {
98 	if (argc == 1) {
99 		debugPrintf("Usage: var <var> (<value>)\n");
100 		return true;
101 	}
102 
103 	if (argc > 2)
104 		_vm->_stack->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2]));
105 
106 	debugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_stack->getVar((uint16)atoi(argv[1])));
107 
108 	return true;
109 }
110 
111 static const char *mystStackNames[12] = {
112 	"Channelwood",
113 	"Credits",
114 	"Demo",
115 	"D'ni",
116 	"Intro",
117 	"MakingOf",
118 	"Mechanical",
119 	"Myst",
120 	"Selenitic",
121 	"Slideshow",
122 	"SneakPreview",
123 	"Stoneship"
124 };
125 
126 static const uint16 default_start_card[12] = {
127 	3137,
128 	10000,
129 	2000,
130 	5038,
131 	1,
132 	1,
133 	6122,
134 	4134,
135 	1282,
136 	1000,
137 	3000,
138 	2029
139 };
140 
Cmd_CurStack(int argc,const char ** argv)141 bool MystConsole::Cmd_CurStack(int argc, const char **argv) {
142 	debugPrintf("Current Stack: %s\n", mystStackNames[_vm->_stack->getStackId()]);
143 	return true;
144 }
145 
Cmd_ChangeStack(int argc,const char ** argv)146 bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) {
147 	if (argc != 2 && argc != 3) {
148 		debugPrintf("Usage: changeStack <stack> [<card>]\n\n");
149 		debugPrintf("Stacks:\n=======\n");
150 
151 		for (byte i = 0; i < ARRAYSIZE(mystStackNames); i++)
152 			debugPrintf(" %s\n", mystStackNames[i]);
153 
154 		debugPrintf("\n");
155 
156 		return true;
157 	}
158 
159 	byte stackNum = 0;
160 
161 	for (byte i = 1; i <= ARRAYSIZE(mystStackNames); i++)
162 		if (!scumm_stricmp(argv[1], mystStackNames[i - 1])) {
163 			stackNum = i;
164 			break;
165 		}
166 
167 	if (!stackNum) {
168 		debugPrintf("\'%s\' is not a stack name!\n", argv[1]);
169 		return true;
170 	}
171 
172 	// We need to stop any playing sound when we change the stack
173 	// as the next card could continue playing it if it.
174 	_vm->_sound->stopEffect();
175 
176 	uint16 card = 0;
177 	if (argc == 3)
178 		card = (uint16)atoi(argv[2]);
179 	else
180 		card = default_start_card[stackNum - 1];
181 
182 	_vm->changeToStack(static_cast<MystStack>(stackNum - 1), card, 0, 0);
183 
184 	return false;
185 }
186 
Cmd_DrawImage(int argc,const char ** argv)187 bool MystConsole::Cmd_DrawImage(int argc, const char **argv) {
188 	if (argc != 2 && argc != 6) {
189 		debugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n");
190 		return true;
191 	}
192 
193 	Common::Rect rect;
194 
195 	if (argc == 2)
196 		rect = Common::Rect(0, 0, 544, 333);
197 	else
198 		rect = Common::Rect((uint16)atoi(argv[2]), (uint16)atoi(argv[3]), (uint16)atoi(argv[4]), (uint16)atoi(argv[5]));
199 
200 	_vm->_gfx->copyImageToScreen((uint16)atoi(argv[1]), rect);
201 	return false;
202 }
203 
Cmd_DrawRect(int argc,const char ** argv)204 bool MystConsole::Cmd_DrawRect(int argc, const char **argv) {
205 	if (argc != 5 && argc != 2) {
206 		debugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n");
207 		debugPrintf("Usage: drawRect <resource id>\n");
208 		return true;
209 	}
210 
211 	if (argc == 5) {
212 		_vm->_gfx->drawRect(Common::Rect((uint16)atoi(argv[1]), (uint16)atoi(argv[2]), (uint16)atoi(argv[3]), (uint16)atoi(argv[4])), kRectEnabled);
213 	} else if (argc == 2) {
214 		uint16 resourceId = (uint16)atoi(argv[1]);
215 		if (resourceId < _vm->getCard()->_resources.size())
216 			_vm->getCard()->_resources[resourceId]->drawBoundingRect();
217 	}
218 
219 	return false;
220 }
221 
Cmd_SetResourceEnable(int argc,const char ** argv)222 bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) {
223 	if (argc < 3) {
224 		debugPrintf("Usage: setResourceEnable <resource id> <bool>\n");
225 		return true;
226 	}
227 
228 	_vm->getCard()->setResourceEnabled((uint16)atoi(argv[1]), atoi(argv[2]) == 1);
229 	return true;
230 }
231 
Cmd_PlaySound(int argc,const char ** argv)232 bool MystConsole::Cmd_PlaySound(int argc, const char **argv) {
233 	if (argc == 1) {
234 		debugPrintf("Usage: playSound <value>\n");
235 
236 		return true;
237 	}
238 
239 	_vm->_sound->playEffect((uint16) atoi(argv[1]));
240 
241 	return false;
242 }
243 
Cmd_StopSound(int argc,const char ** argv)244 bool MystConsole::Cmd_StopSound(int argc, const char **argv) {
245 	debugPrintf("Stopping Sound\n");
246 
247 	_vm->_sound->stopEffect();
248 
249 	return true;
250 }
251 
Cmd_PlayMovie(int argc,const char ** argv)252 bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) {
253 	if (argc < 3) {
254 		debugPrintf("Usage: playMovie <name> <stack> [<left> <top>]\n");
255 		debugPrintf("NOTE: The movie will play *once* in the background.\n");
256 		return true;
257 	}
258 
259 	Common::String fileName = argv[1];
260 	int8 stackNum = -1;
261 	for (byte i = 0; i < ARRAYSIZE(mystStackNames); i++)
262 		if (!scumm_stricmp(argv[2], mystStackNames[i])) {
263 			stackNum = i;
264 			break;
265 		}
266 
267 	if (stackNum < 0) {
268 		debugPrintf("\'%s\' is not a stack name!\n", argv[2]);
269 		return true;
270 	}
271 
272 	VideoEntryPtr video = _vm->playMovie(fileName, static_cast<MystStack>(stackNum));
273 
274 	if (argc == 4) {
275 		video->setX(atoi(argv[2]));
276 		video->setY(atoi(argv[3]));
277 	} else if (argc > 4) {
278 		video->setX(atoi(argv[3]));
279 		video->setY(atoi(argv[4]));
280 	} else {
281 		video->center();
282 	}
283 
284 	return false;
285 }
286 
Cmd_DisableInitOpcodes(int argc,const char ** argv)287 bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) {
288 	if (argc != 1) {
289 		debugPrintf("Usage: disableInitOpcodes\n");
290 
291 		return true;
292 	}
293 
294 	_vm->_stack->disablePersistentScripts();
295 
296 	return true;
297 }
298 
Cmd_Cache(int argc,const char ** argv)299 bool MystConsole::Cmd_Cache(int argc, const char **argv) {
300 	if (argc > 2) {
301 		debugPrintf("Usage: cache on/off - Omit parameter to get current state\n");
302 		return true;
303 	}
304 
305 	bool state = false;
306 
307 	if (argc == 1) {
308 		state = _vm->getCacheState();
309 	} else {
310 		if (!scumm_stricmp(argv[1], "on"))
311 			state = true;
312 
313 		_vm->setCacheState(state);
314 	}
315 
316 	debugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled");
317 	return true;
318 }
319 
Cmd_Resources(int argc,const char ** argv)320 bool MystConsole::Cmd_Resources(int argc, const char **argv) {
321 	debugPrintf("Resources in card %d:\n", _vm->getCard()->getId());
322 
323 	for (uint i = 0; i < _vm->getCard()->_resources.size(); i++) {
324 		debugPrintf("#%2d %s\n", i, _vm->getCard()->_resources[i]->describe().c_str());
325 	}
326 
327 	return true;
328 }
329 
Cmd_QuickTest(int argc,const char ** argv)330 bool MystConsole::Cmd_QuickTest(int argc, const char **argv) {
331 	_debugPauseToken.clear();
332 
333 	// Go through all the ages, all the views and click random stuff
334 	for (uint i = 0; i < ARRAYSIZE(mystStackNames); i++) {
335 		MystStack stackId = static_cast<MystStack>(i);
336 		if (stackId == kDemoStack || stackId == kMakingOfStack
337 		    || stackId == kDemoSlidesStack || stackId == kDemoPreviewStack) continue;
338 
339 		debug("Loading stack %s", mystStackNames[stackId]);
340 		_vm->changeToStack(stackId, default_start_card[stackId], 0, 0);
341 
342 		Common::Array<uint16> ids = _vm->getResourceIDList(ID_VIEW);
343 		for (uint j = 0; j < ids.size(); j++) {
344 			if (ids[j] == 4632) continue;
345 
346 			debug("Loading card %d", ids[j]);
347 			_vm->changeToCard(ids[j], kTransitionCopy);
348 
349 			_vm->doFrame();
350 
351 			{
352 				MystCardPtr card = _vm->getCardPtr();
353 				int16 resIndex = _vm->_rnd->getRandomNumber(card->_resources.size()) - 1;
354 				if (resIndex >= 0 && _vm->getCard()->_resources[resIndex]->isEnabled()) {
355 					card->_resources[resIndex]->handleMouseDown();
356 					card->_resources[resIndex]->handleMouseUp();
357 				}
358 			}
359 
360 			_vm->doFrame();
361 
362 			if (_vm->_stack->getStackId() != stackId) {
363 				// Clicking may have linked us to another age
364 				_vm->changeToStack(stackId, default_start_card[stackId], 0, 0);
365 			}
366 		}
367 	}
368 
369 	_debugPauseToken = _vm->pauseEngine();
370 	return true;
371 }
372 
373 #endif // ENABLE_MYST
374 
375 #ifdef ENABLE_RIVEN
376 
RivenConsole(MohawkEngine_Riven * vm)377 RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) {
378 	registerCmd("changeCard",     WRAP_METHOD(RivenConsole, Cmd_ChangeCard));
379 	registerCmd("curCard",        WRAP_METHOD(RivenConsole, Cmd_CurCard));
380 	registerCmd("dumpCard",       WRAP_METHOD(RivenConsole, Cmd_DumpCard));
381 	registerCmd("var",            WRAP_METHOD(RivenConsole, Cmd_Var));
382 	registerCmd("playSound",      WRAP_METHOD(RivenConsole, Cmd_PlaySound));
383 	registerCmd("playSLST",       WRAP_METHOD(RivenConsole, Cmd_PlaySLST));
384 	registerCmd("stopSound",      WRAP_METHOD(RivenConsole, Cmd_StopSound));
385 	registerCmd("curStack",       WRAP_METHOD(RivenConsole, Cmd_CurStack));
386 	registerCmd("dumpStack",      WRAP_METHOD(RivenConsole, Cmd_DumpStack));
387 	registerCmd("changeStack",    WRAP_METHOD(RivenConsole, Cmd_ChangeStack));
388 	registerCmd("hotspots",       WRAP_METHOD(RivenConsole, Cmd_Hotspots));
389 	registerCmd("zipMode",        WRAP_METHOD(RivenConsole, Cmd_ZipMode));
390 	registerCmd("dumpScript",     WRAP_METHOD(RivenConsole, Cmd_DumpScript));
391 	registerCmd("listZipCards",   WRAP_METHOD(RivenConsole, Cmd_ListZipCards));
392 	registerCmd("getRMAP",        WRAP_METHOD(RivenConsole, Cmd_GetRMAP));
393 	registerCmd("combos",         WRAP_METHOD(RivenConsole, Cmd_Combos));
394 	registerCmd("sliderState",    WRAP_METHOD(RivenConsole, Cmd_SliderState));
395 	registerCmd("quickTest",      WRAP_METHOD(RivenConsole, Cmd_QuickTest));
396 	registerVar("show_hotspots",  &_vm->_showHotspots);
397 }
398 
~RivenConsole()399 RivenConsole::~RivenConsole() {
400 }
401 
402 
Cmd_ChangeCard(int argc,const char ** argv)403 bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) {
404 	if (argc < 2) {
405 		debugPrintf("Usage: changeCard <card>\n");
406 		return true;
407 	}
408 
409 	_vm->_sound->stopSound();
410 	_vm->_sound->stopAllSLST();
411 	_vm->changeToCard((uint16)atoi(argv[1]));
412 
413 	return false;
414 }
415 
Cmd_CurCard(int argc,const char ** argv)416 bool RivenConsole::Cmd_CurCard(int argc, const char **argv) {
417 	debugPrintf("Current Card: %d\n", _vm->getCard()->getId());
418 
419 	return true;
420 }
421 
Cmd_Var(int argc,const char ** argv)422 bool RivenConsole::Cmd_Var(int argc, const char **argv) {
423 	if (argc == 1) {
424 		debugPrintf("Usage: var <var name> (<value>)\n");
425 		return true;
426 	}
427 
428 	if (!_vm->_vars.contains(argv[1])) {
429 		debugPrintf("Unknown variable '%s'\n", argv[1]);
430 		return true;
431 	}
432 
433 	uint32 &var = _vm->_vars[argv[1]];
434 
435 	if (argc > 2)
436 		var = (uint32)atoi(argv[2]);
437 
438 	debugPrintf("%s = %d\n", argv[1], var);
439 	return true;
440 }
441 
Cmd_PlaySound(int argc,const char ** argv)442 bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) {
443 	if (argc < 2) {
444 		debugPrintf("Usage: playSound <value>\n");
445 		return true;
446 	}
447 
448 	_vm->_sound->stopSound();
449 	_vm->_sound->stopAllSLST();
450 	_vm->_sound->playSound((uint16)atoi(argv[1]));
451 	return false;
452 }
453 
Cmd_PlaySLST(int argc,const char ** argv)454 bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) {
455 	if (argc < 2) {
456 		debugPrintf("Usage: playSLST <slst index>\n");
457 
458 		return true;
459 	}
460 
461 	_vm->_sound->stopSound();
462 	_vm->_sound->stopAllSLST();
463 
464 	_vm->getCard()->playSound((uint16)atoi(argv[1]));
465 	return false;
466 }
467 
Cmd_StopSound(int argc,const char ** argv)468 bool RivenConsole::Cmd_StopSound(int argc, const char **argv) {
469 	debugPrintf("Stopping Sound\n");
470 
471 	_vm->_sound->stopSound();
472 	_vm->_sound->stopAllSLST();
473 	return true;
474 }
475 
Cmd_CurStack(int argc,const char ** argv)476 bool RivenConsole::Cmd_CurStack(int argc, const char **argv) {
477 	debugPrintf("Current Stack: %s\n", RivenStacks::getName(_vm->getStack()->getId()));
478 
479 	return true;
480 }
481 
Cmd_ChangeStack(int argc,const char ** argv)482 bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) {
483 	if (argc < 3) {
484 		debugPrintf("Usage: changeStack <stack> <card>\n\n");
485 		debugPrintf("Stacks:\n=======\n");
486 
487 		for (uint i = kStackFirst; i <= kStackLast; i++)
488 			debugPrintf(" %s\n", RivenStacks::getName(i));
489 
490 		debugPrintf("\n");
491 
492 		return true;
493 	}
494 
495 	uint stackId = RivenStacks::getId(argv[1]);
496 	if (stackId == kStackUnknown) {
497 		debugPrintf("\'%s\' is not a stack name!\n", argv[1]);
498 		return true;
499 	}
500 
501 	_vm->changeToStack(stackId);
502 	_vm->changeToCard((uint16)atoi(argv[2]));
503 
504 	return false;
505 }
506 
Cmd_Hotspots(int argc,const char ** argv)507 bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) {
508 	Common::Array<RivenHotspot *> hotspots = _vm->getCard()->getHotspots();
509 
510 	debugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCard()->getId(), hotspots.size());
511 
512 	for (uint16 i = 0; i < hotspots.size(); i++) {
513 		RivenHotspot *hotspot = hotspots[i];
514 		debugPrintf("Hotspot %d, index %d, BLST ID %d (", i, hotspot->getIndex(), hotspot->getBlstId());
515 
516 		if (hotspot->isEnabled())
517 			debugPrintf("enabled");
518 		else
519 			debugPrintf("disabled");
520 
521 		Common::Rect rect = hotspot->getRect();
522 		debugPrintf(") - (%d, %d, %d, %d)\n", rect.left, rect.top, rect.right, rect.bottom);
523 		debugPrintf("    Name = %s\n", hotspot->getName().c_str());
524 	}
525 
526 	return true;
527 }
528 
Cmd_ZipMode(int argc,const char ** argv)529 bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) {
530 	uint32 &zipModeActive = _vm->_vars["azip"];
531 	zipModeActive = !zipModeActive;
532 
533 	debugPrintf("Zip Mode is ");
534 	debugPrintf(zipModeActive ? "Enabled" : "Disabled");
535 	debugPrintf("\n");
536 	return true;
537 }
538 
Cmd_DumpCard(int argc,const char ** argv)539 bool RivenConsole::Cmd_DumpCard(int argc, const char **argv) {
540 	if (argc != 1) {
541 		debugPrintf("Usage: dumpCard\n");
542 		return true;
543 	}
544 
545 	_vm->getCard()->dump();
546 
547 	debugPrintf("Card dump complete.\n");
548 
549 	return true;
550 }
551 
Cmd_DumpStack(int argc,const char ** argv)552 bool RivenConsole::Cmd_DumpStack(int argc, const char **argv) {
553 	if (argc != 1) {
554 		debugPrintf("Usage: dumpStack\n");
555 		return true;
556 	}
557 
558 	_vm->getStack()->dump();
559 
560 	debugPrintf("Stack dump complete.\n");
561 
562 	return true;
563 }
564 
Cmd_DumpScript(int argc,const char ** argv)565 bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) {
566 	if (argc < 4) {
567 		debugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n");
568 		return true;
569 	}
570 
571 	uint16 oldStack = _vm->getStack()->getId();
572 
573 	uint newStack = RivenStacks::getId(argv[1]);
574 	if (newStack == kStackUnknown) {
575 		debugPrintf("\'%s\' is not a stack name!\n", argv[1]);
576 		return true;
577 	}
578 
579 	_vm->changeToStack(newStack);
580 
581 	// Get CARD/HSPT data and dump their scripts
582 	if (!scumm_stricmp(argv[2], "CARD")) {
583 		// Use debugN to print these because the scripts can get very large and would
584 		// really be useless if the the text console is not used. A DumpFile could also
585 		// theoretically be used, but I (clone2727) typically use this dynamically and
586 		// don't want countless files laying around without game context. If one would
587 		// want a file of a script they could just redirect stdout to a file or use
588 		// deriven.
589 		debugN("\n\nDumping scripts for %s\'s card %d!\n", argv[1], (uint16)atoi(argv[3]));
590 		debugN("==================================\n\n");
591 		Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3]));
592 		cardStream->seek(4);
593 		RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream);
594 		for (uint32 i = 0; i < scriptList.size(); i++) {
595 			debugN("Stream Type %d:\n", scriptList[i].type);
596 			scriptList[i].script->dumpScript(0);
597 		}
598 		delete cardStream;
599 	} else if (!scumm_stricmp(argv[2], "HSPT")) {
600 		// See above for why this is printed via debugN
601 		debugN("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3]));
602 		debugN("===========================================\n\n");
603 
604 		Common::SeekableReadStream *hsptStream = _vm->getResource(MKTAG('H','S','P','T'), (uint16)atoi(argv[3]));
605 
606 		uint16 hotspotCount = hsptStream->readUint16BE();
607 
608 		for (uint16 i = 0; i < hotspotCount; i++) {
609 			debugN("Hotspot %d:\n", i);
610 			hsptStream->seek(22, SEEK_CUR);	// Skip non-script related stuff
611 			RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream);
612 			for (uint32 j = 0; j < scriptList.size(); j++) {
613 				debugN("\tStream Type %d:\n", scriptList[j].type);
614 				scriptList[j].script->dumpScript(1);
615 			}
616 		}
617 
618 		delete hsptStream;
619 	} else {
620 		debugPrintf("%s doesn't have any scripts!\n", argv[2]);
621 	}
622 
623 	// See above for why this is printed via debugN
624 	debugN("\n\n");
625 
626 	_vm->changeToStack(oldStack);
627 
628 	debugPrintf("Script dump complete.\n");
629 
630 	return true;
631 }
632 
Cmd_ListZipCards(int argc,const char ** argv)633 bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) {
634 	if (_vm->_zipModeData.size() == 0) {
635 		debugPrintf("No zip card data.\n");
636 	} else {
637 		debugPrintf("Listing zip cards:\n");
638 		for (uint32 i = 0; i < _vm->_zipModeData.size(); i++)
639 			debugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str());
640 	}
641 
642 	return true;
643 }
644 
Cmd_GetRMAP(int argc,const char ** argv)645 bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) {
646 	uint32 rmapCode = _vm->getStack()->getCurrentCardGlobalId();
647 	debugPrintf("RMAP for %s %d = %08x\n", RivenStacks::getName(_vm->getStack()->getId()), _vm->getCard()->getId(), rmapCode);
648 	return true;
649 }
650 
Cmd_Combos(int argc,const char ** argv)651 bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
652 	// In the vain of SCUMM's 'drafts' command, this command will list
653 	// out all combinations needed in Riven, decoded from the variables.
654 	// You'll need to look up the Rebel Tunnel puzzle on your own; the
655 	// solution is constant.
656 
657 	uint32 teleCombo = _vm->_vars["tcorrectorder"];
658 	uint32 prisonCombo = _vm->_vars["pcorrectorder"];
659 	uint32 domeCombo = _vm->_vars["adomecombo"];
660 
661 	debugPrintf("Telescope Combo:\n  ");
662 	for (int i = 0; i < 5; i++)
663 		debugPrintf("%d ", _vm->getStack()->getComboDigit(teleCombo, i));
664 
665 	debugPrintf("\nPrison Combo:\n  ");
666 	for (int i = 0; i < 5; i++)
667 		debugPrintf("%d ", _vm->getStack()->getComboDigit(prisonCombo, i));
668 
669 	debugPrintf("\nDome Combo:\n  ");
670 	for (int i = 1; i <= 25; i++)
671 		if (domeCombo & (1 << (25 - i)))
672 			debugPrintf("%d ", i);
673 
674 	debugPrintf("\n");
675 	return true;
676 }
677 
Cmd_SliderState(int argc,const char ** argv)678 bool RivenConsole::Cmd_SliderState(int argc, const char **argv) {
679 	RivenStacks::DomeSpit *domeSpit = dynamic_cast<RivenStacks::DomeSpit *>(_vm->getStack());
680 	if (!domeSpit) {
681 		debugPrintf("No dome in this stack\n");
682 		return true;
683 	}
684 
685 	if (argc > 1)
686 		domeSpit->setDomeSliderState((uint32)atoi(argv[1]));
687 
688 	debugPrintf("Dome Slider State = %08x\n", domeSpit->getDomeSliderState());
689 	return true;
690 }
691 
Cmd_QuickTest(int argc,const char ** argv)692 bool RivenConsole::Cmd_QuickTest(int argc, const char **argv) {
693 	_debugPauseToken.clear();
694 
695 	// Go through all the stacks, all the cards and click random stuff
696 	for (uint16 stackId = kStackFirst; stackId <= kStackLast; stackId++) {
697 
698 		debug("Loading stack %s", RivenStacks::getName(stackId));
699 		_vm->changeToStack(stackId);
700 
701 		Common::Array<uint16> cardIds = _vm->getResourceIDList(ID_CARD);
702 		for (uint16 i = 0; i < cardIds.size(); i++) {
703 			if (_vm->shouldQuit()) break;
704 
705 			uint16 cardId = cardIds[i];
706 			if (stackId == kStackTspit && cardId == 366) continue; // Cut card with invalid links
707 			if (stackId == kStackTspit && cardId == 412) continue; // Cut card with invalid links
708 			if (stackId == kStackTspit && cardId == 486) continue; // Cut card with invalid links
709 			if (stackId == kStackBspit && cardId == 465) continue; // Cut card with invalid links
710 			if (stackId == kStackJspit && cardId == 737) continue; // Cut card with invalid links
711 
712 			debug("Loading card %d", cardId);
713 			RivenScriptPtr script = _vm->_scriptMan->createScriptFromData(1,
714 			                            kRivenCommandChangeCard, 1, cardId);
715 			_vm->_scriptMan->runScript(script, true);
716 
717 			_vm->_gfx->setTransitionMode(kRivenTransitionModeDisabled);
718 
719 			while (_vm->_scriptMan->hasQueuedScripts()) {
720 				_vm->doFrame();
721 			}
722 
723 			// Click on a random hotspot
724 			Common::Array<RivenHotspot *> hotspots = _vm->getCard()->getHotspots();
725 			if (!hotspots.empty() && _vm->getStack()->getId() != kStackAspit) {
726 				uint hotspotIndex = _vm->_rnd->getRandomNumberRng(0, hotspots.size() - 1);
727 				RivenHotspot *hotspot = hotspots[hotspotIndex];
728 				if (hotspot->isEnabled()) {
729 					Common::Rect hotspotRect = hotspot->getRect();
730 					Common::Point hotspotPoint((hotspotRect.left + hotspotRect.right) / 2, (hotspotRect.top + hotspotRect.bottom) / 2);
731 					_vm->getStack()->onMouseDown(hotspotPoint);
732 					_vm->getStack()->onMouseUp(hotspotPoint);
733 				}
734 
735 				while (_vm->_scriptMan->hasQueuedScripts()) {
736 					_vm->doFrame();
737 				}
738 			}
739 
740 			if (_vm->getStack()->getId() != stackId) {
741 				// Clicking may have linked us to another age
742 				_vm->changeToStack(stackId);
743 			}
744 		}
745 	}
746 
747 	_debugPauseToken = _vm->pauseEngine();
748 	return true;
749 }
750 
751 #endif // ENABLE_RIVEN
752 
LivingBooksConsole(MohawkEngine_LivingBooks * vm)753 LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) {
754 	registerCmd("playSound",			WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound));
755 	registerCmd("stopSound",			WRAP_METHOD(LivingBooksConsole, Cmd_StopSound));
756 	registerCmd("drawImage",			WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage));
757 	registerCmd("changePage",			WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage));
758 	registerCmd("changeCursor",			WRAP_METHOD(LivingBooksConsole, Cmd_ChangeCursor));
759 }
760 
~LivingBooksConsole()761 LivingBooksConsole::~LivingBooksConsole() {
762 }
763 
Cmd_PlaySound(int argc,const char ** argv)764 bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) {
765 	if (argc == 1) {
766 		debugPrintf("Usage: playSound <value>\n");
767 		return true;
768 	}
769 
770 	_vm->_sound->stopSound();
771 	_vm->_sound->playSound((uint16)atoi(argv[1]));
772 	return false;
773 }
774 
Cmd_StopSound(int argc,const char ** argv)775 bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) {
776 	debugPrintf("Stopping Sound\n");
777 
778 	_vm->_sound->stopSound();
779 	return true;
780 }
781 
Cmd_DrawImage(int argc,const char ** argv)782 bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) {
783 	if (argc == 1) {
784 		debugPrintf("Usage: drawImage <value>\n");
785 		return true;
786 	}
787 
788 	_vm->_gfx->copyAnimImageToScreen((uint16)atoi(argv[1]));
789 	_vm->_system->updateScreen();
790 	return false;
791 }
792 
Cmd_ChangePage(int argc,const char ** argv)793 bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) {
794 	if (argc < 2 || argc > 3) {
795 		debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
796 		return true;
797 	}
798 
799 	int page, subpage = 0;
800 	if (sscanf(argv[1], "%d.%d", &page, &subpage) == 0) {
801 		debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
802 		return true;
803 	}
804 	LBMode mode = argc == 2 ? _vm->getCurMode() : (LBMode)atoi(argv[2]);
805 	if (subpage == 0) {
806 		if (_vm->tryLoadPageStart(mode, page))
807 			return false;
808 	} else {
809 		if (_vm->loadPage(mode, page, subpage))
810 			return false;
811 	}
812 	debugPrintf("no such page %d.%d\n", page, subpage);
813 	return true;
814 }
815 
Cmd_ChangeCursor(int argc,const char ** argv)816 bool LivingBooksConsole::Cmd_ChangeCursor(int argc, const char **argv) {
817 	if (argc == 1) {
818 		debugPrintf("Usage: changeCursor <value>\n");
819 		return true;
820 	}
821 
822 	_vm->_cursor->setCursor((uint16)atoi(argv[1]));
823 	return true;
824 }
825 
826 #ifdef ENABLE_CSTIME
827 
CSTimeConsole(MohawkEngine_CSTime * vm)828 CSTimeConsole::CSTimeConsole(MohawkEngine_CSTime *vm) : GUI::Debugger(), _vm(vm) {
829 	registerCmd("playSound",			WRAP_METHOD(CSTimeConsole, Cmd_PlaySound));
830 	registerCmd("stopSound",			WRAP_METHOD(CSTimeConsole, Cmd_StopSound));
831 	registerCmd("drawImage",			WRAP_METHOD(CSTimeConsole, Cmd_DrawImage));
832 	registerCmd("drawSubimage",			WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage));
833 	registerCmd("changeCase",			WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase));
834 	registerCmd("changeScene",			WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene));
835 	registerCmd("caseVariable",			WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable));
836 	registerCmd("invItem",			WRAP_METHOD(CSTimeConsole, Cmd_InvItem));
837 }
838 
~CSTimeConsole()839 CSTimeConsole::~CSTimeConsole() {
840 }
841 
Cmd_PlaySound(int argc,const char ** argv)842 bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) {
843 	if (argc == 1) {
844 		debugPrintf("Usage: playSound <value>\n");
845 		return true;
846 	}
847 
848 	_vm->_sound->stopSound();
849 	_vm->_sound->playSound((uint16)atoi(argv[1]));
850 	return false;
851 }
852 
Cmd_StopSound(int argc,const char ** argv)853 bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) {
854 	debugPrintf("Stopping Sound\n");
855 
856 	_vm->_sound->stopSound();
857 	return true;
858 }
859 
Cmd_DrawImage(int argc,const char ** argv)860 bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) {
861 	if (argc == 1) {
862 		debugPrintf("Usage: drawImage <value>\n");
863 		return true;
864 	}
865 
866 	_vm->_gfx->copyAnimImageToScreen((uint16)atoi(argv[1]));
867 	_vm->_system->updateScreen();
868 	return false;
869 }
870 
Cmd_DrawSubimage(int argc,const char ** argv)871 bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) {
872 	if (argc < 3) {
873 		debugPrintf("Usage: drawSubimage <value> <subimage>\n");
874 		return true;
875 	}
876 
877 	_vm->_gfx->copyAnimSubImageToScreen((uint16)atoi(argv[1]), (uint16)atoi(argv[2]));
878 	_vm->_system->updateScreen();
879 	return false;
880 }
881 
Cmd_ChangeCase(int argc,const char ** argv)882 bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) {
883 	if (argc < 2) {
884 		debugPrintf("Usage: changeCase <value>\n");
885 		return true;
886 	}
887 
888 	error("Can't change case yet"); // FIXME
889 	return false;
890 }
891 
Cmd_ChangeScene(int argc,const char ** argv)892 bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) {
893 	if (argc < 2) {
894 		debugPrintf("Usage: changeScene <value>\n");
895 		return true;
896 	}
897 
898 	_vm->addEvent(CSTimeEvent(kCSTimeEventNewScene, 0xffff, atoi(argv[1])));
899 	return false;
900 }
901 
Cmd_CaseVariable(int argc,const char ** argv)902 bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) {
903 	if (argc < 2) {
904 		debugPrintf("Usage: caseVariable <id> [<value>]\n");
905 		return true;
906 	}
907 
908 	if (argc == 2) {
909 		debugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]);
910 	} else {
911 		_vm->_caseVariable[atoi(argv[1])] = atoi(argv[2]);
912 	}
913 	return true;
914 }
915 
Cmd_InvItem(int argc,const char ** argv)916 bool CSTimeConsole::Cmd_InvItem(int argc, const char **argv) {
917 	if (argc < 3) {
918 		debugPrintf("Usage: invItem <id> <0 or 1>\n");
919 		return true;
920 	}
921 
922 	if (atoi(argv[2])) {
923 		_vm->addEvent(CSTimeEvent(kCSTimeEventDropItemInInventory, 0xffff, atoi(argv[1])));
924 	} else {
925 		_vm->addEvent(CSTimeEvent(kCSTimeEventRemoveItemFromInventory, 0xffff, atoi(argv[1])));
926 	}
927 	return false;
928 }
929 
930 #endif // ENABLE_CSTIME
931 
932 } // End of namespace Mohawk
933