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/file.h"
24 #include "xeen/xeen.h"
25 #include "xeen/debugger.h"
26 
27 namespace Xeen {
28 
strToInt(const char * s)29 static int strToInt(const char *s) {
30 	size_t size = strlen(s);
31 
32 	if (size == 0)
33 		// No string at all
34 		return 0;
35 
36 	if (toupper(s[size - 1]) != 'H')
37 		// Standard decimal string
38 		return atoi(s);
39 
40 	// Hexadecimal string
41 	uint tmp = 0;
42 	int read = sscanf(s, "%xh", &tmp);
43 	if (read < 1)
44 		error("strToInt failed on string \"%s\"", s);
45 	return (int)tmp;
46 }
47 
48 /*------------------------------------------------------------------------*/
49 
Debugger(XeenEngine * vm)50 Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm),
51 		_spellId(-1), _invincible(false), _intangible(false), _superStrength(false) {
52 	registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
53 	registerCmd("spell", WRAP_METHOD(Debugger, cmdSpell));
54 	registerCmd("spells", WRAP_METHOD(Debugger, cmdSpells));
55 	registerCmd("dump", WRAP_METHOD(Debugger, cmdDump));
56 	registerCmd("gold", WRAP_METHOD(Debugger, cmdGold));
57 	registerCmd("gems", WRAP_METHOD(Debugger, cmdGems));
58 	registerCmd("map", WRAP_METHOD(Debugger, cmdMap));
59 	registerCmd("pos", WRAP_METHOD(Debugger, cmdPos));
60 	registerCmd("invincible", WRAP_METHOD(Debugger, cmdInvincible));
61 	registerCmd("strength", WRAP_METHOD(Debugger, cmdSuperStrength));
62 	registerCmd("intangible", WRAP_METHOD(Debugger, cmdIntangible));
63 }
64 
onFrame()65 void Debugger::onFrame() {
66 	if (_spellId != -1) {
67 		// Cast any specified spell
68 		MagicSpell spellId = (MagicSpell)_spellId;
69 		_spellId = -1;
70 		Character *c = &_vm->_party->_activeParty[0];
71 		c->_currentSp = 99;
72 		_vm->_spells->castSpell(c, spellId);
73 	}
74 
75 	GUI::Debugger::onFrame();
76 }
77 
cmdSpell(int argc,const char ** argv)78 bool Debugger::cmdSpell(int argc, const char **argv) {
79 	if (argc != 2) {
80 		debugPrintf("Format: spell <spell-id>");
81 		return true;
82 	} else {
83 		int spellId = strToInt(argv[1]);
84 		if (spellId >= MS_AcidSpray && spellId <= MS_WizardEye) {
85 			_spellId = spellId;
86 			return false;
87 		}
88 	}
89 
90 	return true;
91 }
92 
cmdSpells(int argc,const char ** argv)93 bool Debugger::cmdSpells(int argc, const char **argv) {
94 	Party &party = *_vm->_party;
95 
96 	for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
97 		Character &c = party._activeParty[charIdx];
98 		Common::fill(c._spells, c._spells + SPELLS_PER_CLASS, true);
99 		c._currentSp = 9999;
100 	}
101 
102 	party._gems += 1000;
103 
104 	debugPrintf("Spells given to party.\n");
105 	return true;
106 }
107 
cmdDump(int argc,const char ** argv)108 bool Debugger::cmdDump(int argc, const char **argv) {
109 	File f;
110 
111 	if (argc < 2) {
112 		debugPrintf("Format: dump <resource name>\n");
113 	} else {
114 		if (argc == 2)
115 			f.open(argv[1]);
116 
117 		if (f.isOpen()) {
118 			Common::DumpFile df;
119 			df.open(argv[1]);
120 
121 			size_t size = f.size();
122 			byte *data = new byte[size];
123 
124 			if (f.read(data, size) == size) {
125 				df.write(data, size);
126 
127 			} else {
128 				debugPrintf("Failed to read %zu bytes from '%s'\n", size, argv[1]);
129 			}
130 
131 			f.close();
132 			df.close();
133 			delete[] data;
134 			debugPrintf("Saved\n");
135 		} else {
136 			debugPrintf("Could not find resource with that name\n");
137 		}
138 	}
139 
140 	return true;
141 }
142 
cmdGold(int argc,const char ** argv)143 bool Debugger::cmdGold(int argc, const char **argv) {
144 	Party &party = *_vm->_party;
145 	if (argc == 1) {
146 		debugPrintf("Current gold: %d, bank: %d\n", party._gold, party._bankGold);
147 	} else {
148 		party._gold = strToInt(argv[1]);
149 		if (argc > 2)
150 			party._bankGold = strToInt(argv[2]);
151 	}
152 
153 	return true;
154 }
155 
cmdGems(int argc,const char ** argv)156 bool Debugger::cmdGems(int argc, const char **argv) {
157 	Party &party = *_vm->_party;
158 	if (argc == 1) {
159 		debugPrintf("Current gems: %d, bank: %d\n", party._gems, party._bankGems);
160 	} else {
161 		party._gems = strToInt(argv[1]);
162 		if (argc > 2)
163 			party._bankGems = strToInt(argv[2]);
164 	}
165 
166 	return true;
167 }
168 
cmdMap(int argc,const char ** argv)169 bool Debugger::cmdMap(int argc, const char **argv) {
170 	if (argc < 2) {
171 		debugPrintf("map mapId [ xp, yp ] [ sideNum ]\n");
172 		return true;
173 	} else {
174 		Map &map = *g_vm->_map;
175 		Party &party = *g_vm->_party;
176 
177 		int mapId = strToInt(argv[1]);
178 		int x = argc < 3 ? 8 : strToInt(argv[2]);
179 		int y = argc < 4 ? 8 : strToInt(argv[3]);
180 
181 		if (argc == 5)
182 			map._loadCcNum = strToInt(argv[4]);
183 		map.load(mapId);
184 		party._mazePosition.x = x;
185 		party._mazePosition.y = y;
186 		party._mazeDirection = DIR_NORTH;
187 		return false;
188 	}
189 }
190 
cmdPos(int argc,const char ** argv)191 bool Debugger::cmdPos(int argc, const char **argv) {
192 	Party &party = *g_vm->_party;
193 
194 	if (argc < 3) {
195 		debugPrintf("pos xp, yp\n");
196 		return true;
197 	} else {
198 		party._mazePosition.x = strToInt(argv[1]);
199 		party._mazePosition.y = strToInt(argv[2]);
200 		party._stepped = true;
201 		return false;
202 	}
203 }
204 
cmdInvincible(int argc,const char ** argv)205 bool Debugger::cmdInvincible(int argc, const char **argv) {
206 	_invincible = (argc < 2) || strcmp(argv[1], "off");
207 	debugPrintf("Invincibility is %s\n", _invincible ? "on" : "off");
208 	return true;
209 }
210 
cmdSuperStrength(int argc,const char ** argv)211 bool Debugger::cmdSuperStrength(int argc, const char **argv) {
212 	_superStrength = (argc < 2) || strcmp(argv[1], "off");
213 	debugPrintf("Super-powered attacks are %s\n", _superStrength ? "on" : "off");
214 	return true;
215 }
216 
cmdIntangible(int argc,const char ** argv)217 bool Debugger::cmdIntangible(int argc, const char **argv) {
218 	_intangible = (argc < 2) || strcmp(argv[1], "off");
219 	debugPrintf("Intangibility is %s\n", _intangible ? "on" : "off");
220 	return true;
221 }
222 
223 } // End of namespace Xeen
224