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/endian.h"
25 #include "lure/luredefs.h"
26 #include "lure/debugger.h"
27 #include "lure/decode.h"
28 #include "lure/game.h"
29 #include "lure/res.h"
30 #include "lure/res_struct.h"
31 #include "lure/room.h"
32 #include "lure/scripts.h"
33 #include "lure/strings.h"
34 
35 namespace Lure {
36 
Debugger()37 Debugger::Debugger(): GUI::Debugger() {
38 	registerCmd("continue",			WRAP_METHOD(Debugger, cmdExit));
39 	registerCmd("enter",				WRAP_METHOD(Debugger, cmd_enterRoom));
40 	registerCmd("rooms",				WRAP_METHOD(Debugger, cmd_listRooms));
41 	registerCmd("fields",				WRAP_METHOD(Debugger, cmd_listFields));
42 	registerCmd("setfield",			WRAP_METHOD(Debugger, cmd_setField));
43 	registerCmd("queryfield",			WRAP_METHOD(Debugger, cmd_queryField));
44 	registerCmd("give",				WRAP_METHOD(Debugger, cmd_giveItem));
45 	registerCmd("hotspots",			WRAP_METHOD(Debugger, cmd_hotspots));
46 	registerCmd("hotspot",			WRAP_METHOD(Debugger, cmd_hotspot));
47 	registerCmd("room",				WRAP_METHOD(Debugger, cmd_room));
48 	registerCmd("showanim",			WRAP_METHOD(Debugger, cmd_showAnim));
49 	registerCmd("strings",			WRAP_METHOD(Debugger, cmd_saveStrings));
50 	registerCmd("debug",				WRAP_METHOD(Debugger, cmd_debug));
51 	registerCmd("script",				WRAP_METHOD(Debugger, cmd_script));
52 }
53 
strToInt(const char * s)54 static int strToInt(const char *s) {
55 	if (!*s)
56 		// No string at all
57 		return 0;
58 	else if (strcmp(s, "player") == 0)
59 		return PLAYER_ID;
60 	else if (strcmp(s, "ratpouch") == 0)
61 		return RATPOUCH_ID;
62 	else if (toupper(s[strlen(s) - 1]) != 'H')
63 		// Standard decimal string
64 		return atoi(s);
65 
66 	// Hexadecimal string
67 	int result = 0;
68 	const char *p = s;
69 	char ch;
70 	while ((ch = toupper(*p++)) != 'H') {
71 		if ((ch >= '0') && (ch <= '9'))
72 			result = (result << 4) + (ch - '0');
73 		else if ((ch >= 'A') && (ch <= 'F'))
74 			result = (result << 4) + (ch - 'A' + 10);
75 		else
76 			break;
77 	}
78 	return result;
79 }
80 
cmd_enterRoom(int argc,const char ** argv)81 bool Debugger::cmd_enterRoom(int argc, const char **argv) {
82 	Resources &res = Resources::getReference();
83 	Room &room = Room::getReference();
84 	uint remoteFlag = 0;
85 
86 	if (argc > 1) {
87 		int roomNumber = strToInt(argv[1]);
88 
89 		// Validate that it's an existing room
90 		if (res.getRoom(roomNumber) == NULL) {
91 			debugPrintf("specified number was not a valid room\n");
92 			return true;
93 		}
94 
95 		if (argc > 2) {
96 			remoteFlag = strToInt(argv[2]);
97 		}
98 
99 		room.leaveRoom();
100 		room.setRoomNumber(roomNumber);
101 		if (!remoteFlag)
102 			res.getActiveHotspot(PLAYER_ID)->setRoomNumber(roomNumber);
103 
104 		detach();
105 		return false;
106 	}
107 
108 	debugPrintf("Syntax: room <roomnum> [<remoteview>]\n");
109 	debugPrintf("A non-zero value for reomteview will change the room without ");
110 	debugPrintf("moving the player.\n");
111 	return true;
112 }
113 
cmd_listRooms(int argc,const char ** argv)114 bool Debugger::cmd_listRooms(int argc, const char **argv) {
115 	RoomDataList &rooms = Resources::getReference().roomData();
116 	StringData &strings = StringData::getReference();
117 	char buffer[MAX_DESC_SIZE];
118 	int ctr = 0;
119 
120 	debugPrintf("Available rooms are:\n");
121 	for (RoomDataList::iterator i = rooms.begin(); i != rooms.end(); ++i) {
122 		RoomData const &room = **i;
123 		// Explictly note the second drawbridge room as "Alt"
124 		if (room.roomNumber == 49) {
125 			strings.getString(47, buffer);
126 			strcat(buffer, " (alt)");
127 		} else {
128 			strings.getString(room.roomNumber, buffer);
129 		}
130 
131 		debugPrintf("#%d - %s", room.roomNumber, buffer);
132 
133 		if (++ctr % 3 == 0) debugPrintf("\n");
134 		else {
135 			// Write out spaces between columns
136 			int numSpaces = 25 - strlen(buffer) - (room.roomNumber >= 10 ? 2 : 1);
137 			char *s = buffer;
138 			while (numSpaces-- > 0) *s++ = ' ';
139 			*s = '\0';
140 			debugPrintf("%s", buffer);
141 		}
142 	}
143 	debugPrintf("\n");
144 	debugPrintf("Current room: %d\n", Room::getReference().roomNumber());
145 
146 	return true;
147 }
148 
cmd_listFields(int argc,const char ** argv)149 bool Debugger::cmd_listFields(int argc, const char **argv) {
150 	ValueTableData &fields = Resources::getReference().fieldList();
151 
152 	for (int ctr = 0; ctr < fields.size(); ++ctr) {
153 		debugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr));
154 		if (!((ctr + 1) % 7))
155 			debugPrintf("\n");
156 	}
157 	debugPrintf("\n");
158 	return true;
159 }
160 
cmd_setField(int argc,const char ** argv)161 bool Debugger::cmd_setField(int argc, const char **argv) {
162 	ValueTableData &fields = Resources::getReference().fieldList();
163 
164 	if (argc >= 3) {
165 		int fieldNum = strToInt(argv[1]);
166 		uint16 value = strToInt(argv[2]);
167 
168 		if ((fieldNum < 0) || (fieldNum >= fields.size())) {
169 			// Invalid field number
170 			debugPrintf("Invalid field number specified\n");
171 		} else {
172 			// Set the field value
173 			fields.setField(fieldNum, value);
174 		}
175 	} else {
176 		debugPrintf("Syntax: setfield <field_number> <value>\n");
177 	}
178 
179 	return true;
180 }
181 
cmd_queryField(int argc,const char ** argv)182 bool Debugger::cmd_queryField(int argc, const char **argv) {
183 	ValueTableData &fields = Resources::getReference().fieldList();
184 
185 	if (argc > 1) {
186 		int fieldNum = strToInt(argv[1]);
187 		if ((fieldNum < 0) || (fieldNum >= fields.size())) {
188 			// Invalid field number
189 			debugPrintf("Invalid field number specified\n");
190 		} else {
191 			// Get the field value
192 			debugPrintf("Field %d is %d (%xh)\n", fieldNum,
193 				fields.getField(fieldNum), fields.getField(fieldNum));
194 		}
195 	} else {
196 		debugPrintf("Syntax: queryfield <field_num>\n");
197 	}
198 
199 	return true;
200 }
201 
cmd_giveItem(int argc,const char ** argv)202 bool Debugger::cmd_giveItem(int argc, const char **argv) {
203 	Resources &res = Resources::getReference();
204 	uint16 itemNum;
205 	uint16 charNum = PLAYER_ID;
206 	HotspotData *charHotspot, *itemHotspot;
207 
208 	if (argc >= 2) {
209 		itemNum = strToInt(argv[1]);
210 
211 		if (argc == 3)
212 			charNum = strToInt(argv[2]);
213 
214 		itemHotspot = res.getHotspot(itemNum);
215 		charHotspot = res.getHotspot(charNum);
216 
217 		if (itemHotspot == NULL) {
218 			debugPrintf("The specified item does not exist\n");
219 		} else if (itemNum < 0x408) {
220 			debugPrintf("The specified item number is not an object\n");
221 		} else if ((charNum < PLAYER_ID) || (charNum >= 0x408) ||
222 				   (charHotspot == NULL)) {
223 			debugPrintf("The specified character does not exist");
224 		} else {
225 			// Set the item's room number to be the destination character
226 			itemHotspot->roomNumber = charNum;
227 		}
228 	} else {
229 		debugPrintf("Syntax: give <item_id> [<character_id>]\n");
230 	}
231 
232 	return true;
233 }
234 
cmd_hotspots(int argc,const char ** argv)235 bool Debugger::cmd_hotspots(int argc, const char **argv) {
236 	Resources &res = Resources::getReference();
237 	StringData &strings = StringData::getReference();
238 	Room &room = Room::getReference();
239 	char buffer[MAX_DESC_SIZE];
240 
241 	if (argc > 1) {
242 		if (strcmp(argv[1], "active") == 0) {
243 			// Loop for displaying active hotspots
244 			HotspotList::iterator i;
245 			for (i = res.activeHotspots().begin(); i != res.activeHotspots().end(); ++i) {
246 				Hotspot const &hotspot = **i;
247 
248 				if (hotspot.nameId() == 0) strcpy(buffer, "none");
249 				else strings.getString(hotspot.nameId(), buffer);
250 
251 				debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer,
252 					hotspot.x(), hotspot.y(), hotspot.roomNumber());
253 			}
254 		} else {
255 			// Presume it's a room's hotspots
256 			uint16 roomNumber = (argc >= 3) ? strToInt(argv[2]) : room.roomNumber();
257 
258 			HotspotDataList::iterator i;
259 			for (i = res.hotspotData().begin(); i != res.hotspotData().end(); ++i) {
260 				HotspotData const &hotspot = **i;
261 
262 				if (hotspot.roomNumber == roomNumber) {
263 					if (hotspot.nameId == 0) strcpy(buffer, "none");
264 					else strings.getString(hotspot.nameId, buffer);
265 
266 					debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer,
267 					hotspot.startX, hotspot.startY, hotspot.roomNumber);
268 				}
269 			}
270 		}
271 
272 	} else {
273 		debugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n");
274 		debugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n");
275 		debugPrintf("present in either the current room or a designated one\n");
276 	}
277 
278 	return true;
279 }
280 
cmd_hotspot(int argc,const char ** argv)281 bool Debugger::cmd_hotspot(int argc, const char **argv) {
282 	Resources &res = Resources::getReference();
283 	StringData &strings = StringData::getReference();
284 	StringList &stringList = res.stringList();
285 	char buffer[MAX_DESC_SIZE];
286 	HotspotData *hs;
287 	Hotspot *h;
288 
289 	if (argc < 2) {
290 		debugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n");
291 		return true;
292 	}
293 	hs = res.getHotspot(strToInt(argv[1]));
294 	if (!hs) {
295 		debugPrintf("Unknown hotspot specified\n");
296 		return true;
297 	}
298 
299 	h = res.getActiveHotspot(hs->hotspotId);
300 	if (argc == 2) {
301 		// Show the hotspot properties
302 		strings.getString(hs->nameId, buffer);
303 		debugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer,
304 			hs->descId, hs->descId2);
305 		debugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset);
306 		debugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer);
307 		debugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber);
308 		debugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n",
309 			hs->width, hs->height,  hs->widthCopy, hs->heightCopy, hs->yCorrection);
310 		debugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY);
311 		debugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag);
312 		debugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset);
313 		debugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n",
314 			hs->talkScriptOffset, hs->tickScriptOffset);
315 		debugPrintf("Tick Proc offset = %xh\n", hs->tickProcId);
316 		debugPrintf("Tick timeout = %d\n", hs->tickTimeout);
317 		debugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n",
318 			hs->characterMode, hs->delayCtr, hs->pauseCtr);
319 
320 		if (h != NULL) {
321 			debugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames());
322 			debugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false");
323 		}
324 
325 	} else if (strcmp(argv[2], "actions") == 0) {
326 			// List the action set for the character
327 			for (int action = GET; action <= EXAMINE; ++action) {
328 				uint16 offset = res.getHotspotAction(hs->actionsOffset, (Action) action);
329 				const char *actionStr = stringList.getString(action);
330 
331 				if (offset >= 0x8000) {
332 					debugPrintf("%s - Message %xh\n",  actionStr, offset & 0x7ff);
333 				} else if (offset != 0) {
334 					debugPrintf("%s - Script %xh\n", actionStr, offset);
335 				}
336 			}
337 	} else if (strcmp(argv[2], "activate") == 0) {
338 		// Activate the hotspot
339 		res.activateHotspot(hs->hotspotId);
340 		hs->flags &= ~HOTSPOTFLAG_MENU_EXCLUSION;
341 		debugPrintf("Activated\n");
342 
343 	} else if (strcmp(argv[2], "deactivate") == 0) {
344 		// Deactivate the hotspot
345 		res.deactivateHotspot(hs->hotspotId);
346 		hs->flags |= HOTSPOTFLAG_MENU_EXCLUSION;
347 		debugPrintf("Deactivated\n");
348 
349 	} else {
350 		if (strcmp(argv[2], "schedule") == 0) {
351 			// List any current schedule for the character
352 			debugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str());
353 		}
354 		if (!h)
355 			debugPrintf("The specified hotspot is not currently active\n");
356 		else if (strcmp(argv[2], "paths") == 0) {
357 			// List any paths for a charcter
358 			debugPrintf("%s", h->pathFinder().getDebugInfo().c_str());
359 		}
360 		else if (strcmp(argv[2], "pixels") == 0) {
361 			// List the pixel data for the hotspot
362 			HotspotAnimData &pData = h->anim();
363 			debugPrintf("Record Id = %xh\n", pData.animRecordId);
364 			debugPrintf("Flags = %d\n", pData.flags);
365 			debugPrintf("Frames: up=%d down=%d left=%d right=%d\n",
366 				pData.upFrame, pData.downFrame, pData.leftFrame, pData.rightFrame);
367 			debugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames());
368 		}
369 		else if (strcmp(argv[2], "setpos") == 0) {
370 			// Set the hotspot position
371 			if (argc >= 5)
372 				h->setPosition(strToInt(argv[3]), strToInt(argv[4]));
373 			if (argc >= 6)
374 				h->setRoomNumber(strToInt(argv[5]));
375 			debugPrintf("Done.\n");
376 		}
377 	}
378 
379 	debugPrintf("\n");
380 	return true;
381 }
382 
383 const char *directionList[5] = {"UP", "DOWN", "LEFT", "RIGHT", "NONE"};
384 
cmd_room(int argc,const char ** argv)385 bool Debugger::cmd_room(int argc, const char **argv) {
386 	Resources &res = Resources::getReference();
387 	StringData &strings = StringData::getReference();
388 	char buffer[MAX_DESC_SIZE];
389 
390 	if (argc < 2) {
391 		debugPrintf("room <room_number>\n");
392 		return true;
393 	}
394 	int roomNumber = strToInt(argv[1]);
395 	RoomData *room = res.getRoom(roomNumber);
396 	if (!room) {
397 		debugPrintf("Unknown room specified\n");
398 		return true;
399 	}
400 
401 	// Show the room details
402 	strings.getString(roomNumber, buffer);
403 	debugPrintf("room #%d - %s\n", roomNumber,  buffer);
404 	strings.getString(room->descId, buffer);
405 	debugPrintf("%s\n", buffer);
406 	debugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n",
407 		room->clippingXStart, room->clippingXEnd,
408 		room->walkBounds.left, room->walkBounds.top,
409 		room->walkBounds.right, room->walkBounds.bottom);
410 
411 	debugPrintf("Exit hotspots:");
412 	RoomExitHotspotList &exits = room->exitHotspots;
413 	if (exits.empty())
414 		debugPrintf(" none\n");
415 	else {
416 		RoomExitHotspotList::iterator i;
417 		for (i = exits.begin(); i != exits.end(); ++i) {
418 			RoomExitHotspotData const &rec = **i;
419 
420 			debugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh",
421 				rec.xs, rec.ys, rec.xe, rec.ye, rec.destRoomNumber, rec.cursorNum, rec.hotspotId);
422 		}
423 
424 		debugPrintf("\n");
425 	}
426 
427 	debugPrintf("Room exits:");
428 	if (room->exits.empty())
429 		debugPrintf(" none\n");
430 	else {
431 		RoomExitList::iterator i2;
432 		for (i2 = room->exits.begin(); i2 != room->exits.end(); ++i2) {
433 			RoomExitData const &rec2 = **i2;
434 
435 			debugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh",
436 				rec2.xs, rec2.ys, rec2.xe, rec2.ye, rec2.roomNumber,
437 				rec2.x, rec2.y, directionList[rec2.direction], rec2.sequenceOffset);
438 		}
439 
440 		debugPrintf("\n");
441 	}
442 
443 	return true;
444 }
445 
cmd_showAnim(int argc,const char ** argv)446 bool Debugger::cmd_showAnim(int argc, const char **argv) {
447 	Resources &res = Resources::getReference();
448 	if (argc < 2) {
449 		debugPrintf("showAnim animId [[frame_width frame_height] | list]\n");
450 		return true;
451 	}
452 
453 	// Get the animation Id
454 	int animId = strToInt(argv[1]);
455 	HotspotAnimData *data = res.getAnimation(animId);
456 	if (data == NULL) {
457 		debugPrintf("No such animation Id exists\n");
458 		return true;
459 	}
460 
461 	// Figure out the total size of the animation - this will be used for guestimating
462 	// frame sizes, or validating that a specified frame size is correct
463 	MemoryBlock *src = Disk::getReference().getEntry(data->animId);
464 
465 	int numFrames = READ_LE_UINT16(src->data());
466 	uint16 *headerEntry = (uint16 *) (src->data() + 2);
467 	assert((numFrames >= 1) && (numFrames < 100));
468 
469 	// Calculate total needed size for output and create memory block to hold it
470 	uint32 totalSize = 0;
471 	for (uint16 ctr = 0; ctr < numFrames; ++ctr, ++headerEntry) {
472 		totalSize += (READ_LE_UINT16(headerEntry) + 31) / 32;
473 	}
474 	totalSize = (totalSize + 0x81) << 4;
475 	MemoryBlock *dest = Memory::allocate(totalSize);
476 
477 	uint32 srcStart = (numFrames + 1) * sizeof(uint16) + 6;
478 	uint32 destSize = AnimationDecoder::decode_data(src, dest, srcStart) - 0x40;
479 
480 	// Figure out the frame size
481 	int frameSize;
482 
483 	if ((data->flags & PIXELFLAG_HAS_TABLE) != 0) {
484 		// Table based animation, so get frame size from frame 1 offset
485 		frameSize = READ_LE_UINT16(src->data());
486 	} else {
487 		// Get frame size from dividing uncompressed size by number of frames
488 		frameSize = destSize / numFrames;
489 	}
490 
491 	// Free up the data
492 	delete src;
493 	delete dest;
494 
495 	int width, height;
496 
497 	if (argc == 4) {
498 		// Width and height specified
499 		width = strToInt(argv[2]);
500 		height = strToInt(argv[3]);
501 
502 		if ((width * height) != (frameSize * 2)) {
503 			debugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n",
504 				destSize, width, height, numFrames, width * height * numFrames / 2);
505 		}
506 	} else {
507 		// Guestimate a frame size
508 		frameSize = destSize / numFrames;
509 
510 		// Figure out the approximate starting point of a width 3/4 the frame size
511 		width = frameSize * 3 / 4;
512 
513 		bool descFlag = (argc == 3);
514 		if (descFlag) debugPrintf("Target size = %d\n", frameSize * 2);
515 
516 		while ((width > 0) && (descFlag || (((frameSize * 2) % width) != 0))) {
517 			if (((frameSize * 2) % width) == 0)
518 				debugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width);
519 			--width;
520 		}
521 
522 		if (argc == 3) {
523 			debugPrintf("Done\n");
524 			return true;
525 		} else if (width == 0) {
526 			debugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n",
527 				destSize, numFrames, frameSize);
528 			return true;
529 		}
530 
531 		height = (frameSize * 2) / width;
532 		debugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n",
533 			numFrames, width, height);
534 	}
535 
536 	// Bottle object is used as a handy hotspot holder that doesn't have any
537 	// tick proc behavior that we need to worry about
538 	Hotspot *hotspot = res.activateHotspot(BOTTLE_HOTSPOT_ID);
539 	hotspot->setLayer(0xfe);
540 	hotspot->setSize(width, height);
541 
542 	Hotspot *player = res.activateHotspot(PLAYER_ID);
543 	hotspot->setColorOffset(player->resource()->colorOffset);
544 
545 	hotspot->setAnimation(animId);
546 
547 	debugPrintf("Done\n");
548 	return true;
549 }
550 
cmd_saveStrings(int argc,const char ** argv)551 bool Debugger::cmd_saveStrings(int argc, const char **argv) {
552 	if (argc != 2) {
553 		debugPrintf("strings <stringId>\n");
554 		return true;
555 	}
556 
557 	StringData &strings = StringData::getReference();
558 
559 	char *buffer = (char *)malloc(32768);
560 	if (!buffer) {
561 		debugPrintf("Cannot allocate strings buffer\n");
562 		return true;
563 	}
564 
565 	uint16 id = strToInt(argv[1]);
566 	strings.getString(id, buffer);
567 	debugPrintf("%s\n", buffer);
568 
569 /* Commented out code for saving all text strings - note that 0x1000 is chosen
570  * arbitrarily, so there'll be a bunch of garbage at the end, or the game will crash
571 
572 	// Save all the strings to a text file - this
573 
574 	FILE *f = fopen("strings.txt", "w");
575 
576 	for (int index = 0; index < 0x1000; ++index) {
577 		strings.getString(index, buffer);
578 		fprintf(f, "%.4xh - %s\n", index, buffer);
579 	}
580 
581 	fclose(f);
582 
583 	debugPrintf("Done\n");
584 */
585 
586 	free(buffer);
587 
588 	return true;
589 }
590 
cmd_debug(int argc,const char ** argv)591 bool Debugger::cmd_debug(int argc, const char **argv) {
592 	Game &game = Game::getReference();
593 	Room &room = Room::getReference();
594 
595 	if ((argc == 2) && (strcmp(argv[1], "on") == 0)) {
596 		debugPrintf("debug keys are on\n");
597 		game.debugFlag() = true;
598 
599 	} else if ((argc == 2) && (strcmp(argv[1], "off") == 0)) {
600 		debugPrintf("debug keys are off\n");
601 		game.debugFlag() = false;
602 		room.setShowInfo(false);
603 
604 	} else {
605 		debugPrintf("debug [on | off]]\n");
606 	}
607 
608 	return true;
609 }
610 
cmd_script(int argc,const char ** argv)611 bool Debugger::cmd_script(int argc, const char **argv) {
612 	if (argc < 2) {
613 		debugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n");
614 		return true;
615 	}
616 
617 	int scriptNumber = strToInt(argv[1]);
618 	if ((scriptNumber < 0) || (scriptNumber > 66)) {
619 		debugPrintf("An invalid script number was specified\n");
620 		return true;
621 	}
622 
623 	uint16 param1 = 0, param2 = 0, param3 = 0;
624 	if (argc >= 3)
625 		param1 = strToInt(argv[2]);
626 	if (argc >= 4)
627 		param2 = strToInt(argv[3]);
628 	if (argc >= 5)
629 		param3 = strToInt(argv[4]);
630 
631 	Script::executeMethod(scriptNumber, param1, param2, param3);
632 	debugPrintf("Script executed\n");
633 	return true;
634 }
635 
636 } // End of namespace Lure
637