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 "glk/agt/agility.h"
24 
25 namespace Glk {
26 namespace AGT {
27 
dbgprintf(const char * fmt,...)28 void dbgprintf(const char *fmt, ...) {
29 	va_list vp;
30 	char buff[300];
31 
32 	va_start(vp, fmt);
33 	vsprintf(buff, fmt, vp);
34 	va_end(vp);
35 
36 	debugout(buff);
37 }
38 
39 
print_msg(descr_ptr dptr)40 static void print_msg(descr_ptr dptr) {
41 	int j;
42 	descr_line *txt;
43 
44 	txt = read_descr(dptr.start, dptr.size);
45 	if (txt != NULL) {
46 		for (j = 0; txt[j] != NULL; j++) {
47 			dbgprintf("\n");
48 			debugout(txt[j]);
49 		}
50 	}
51 	free_descr(txt);
52 }
53 
54 
getname(int inum)55 static char *getname(int inum)
56 /* Name should be 20 chars or less */
57 {
58 	if (inum == 0) return rstrdup("* 0 *");
59 	return objname(inum);
60 }
61 
62 
63 extern integer dobj, iobj, actor;
64 
print_special_obj(int i)65 void print_special_obj(int i)
66 /* This is called by the disassembler in agtdbg.c */
67 /* i=0 NOUN, 1 OBJECT, 2 NAME */
68 {
69 	int dval;
70 	char *s;
71 	switch (i) {
72 	case 0:
73 		dval = dobj;
74 		dbgprintf("NOUN");
75 		break;
76 	case 1:
77 		dval = iobj;
78 		dbgprintf("OBJECT");
79 		break;
80 	case 2:
81 		dval = actor;
82 		dbgprintf("NAME");
83 		break;
84 	default:
85 		dval = 0; /* Silence compiler warnings. */
86 		fatal("INTERNAL ERROR: Invalid *dval* in print_special_obj.");
87 	}
88 	if (dbgflagptr == NULL)
89 		/* This determines whether we are linked with agtout or agil */
90 		return;
91 	s = getname(dval);
92 	dbgprintf("(%d:%s)", dval, s);
93 	rfree(s);
94 }
95 
96 #define printval(str,index,ptr) {dbgprintf("[%s%d",str,index);\
97 		if (ptr==NULL) dbgprintf("]");\
98 		else dbgprintf("=%ld]",(long)ptr[index]);}
99 
argout(int dtype,int dval,int optype)100 int argout(int dtype, int dval, int optype) {
101 	char *s;
102 
103 	if (dtype & AGT_VAR) dtype = AGT_VAR;
104 
105 	if ((optype & 3) == 1) /* variable */
106 		dtype = AGT_VAR;
107 	if (optype & 2) { /* NOUN or OBJECT */
108 		if (dtype >= 64 && dtype != AGT_NUM)
109 			dbgprintf("ILL:");
110 		if (optype == 2)
111 			print_special_obj(0); /* NOUN */
112 		else
113 			print_special_obj(1);  /* OBJECT */
114 		return 0;
115 	}
116 
117 	if (!interp_arg)
118 		dbgprintf("%d", dval);
119 	else {
120 		if (dtype < 64) {
121 			if (dval == -1)
122 				print_special_obj(2); /* NAME */
123 			else {
124 				s = getname(dval);
125 				if (dtype & (AGT_ITEM | AGT_CREAT | AGT_SELF | AGT_WORN))
126 					dbgprintf("<%d:%s>", dval, s);
127 				else
128 					dbgprintf("{%d:%s}", dval, s);
129 				rfree(s);
130 			}
131 		} else if ((dtype & AGT_VAR) != 0) {
132 			if (dval == -1)
133 				print_tos();
134 			else
135 				printval("Var", dval, dbgvarptr);
136 		} else switch (dtype) {
137 			case AGT_TIME:
138 				dbgprintf("%2d:%2d", dval / 100, dval % 100);
139 				break;
140 			case AGT_NUM:  /* Numeric */
141 				dbgprintf("%d", dval);
142 				break;
143 			case AGT_FLAG:  /* Flag */
144 				printval("Flg", dval, dbgflagptr);
145 				break;
146 			case AGT_ROOMFLAG: /* Roomflag */
147 				dbgprintf("RoomFlag%d", dval);
148 				break;
149 			case AGT_QUEST:  /* Question */
150 				if (dval <= MaxQuestion && dval >= 1 && question != NULL) {
151 					dbgprintf("\nQ%d:%s\n", dval, question[dval - 1]);
152 					dbgprintf("[A:%s]", answer[dval - 1]);
153 				} else if (quest_ptr != NULL) {
154 					dbgprintf("\nQ%d: ", dval);
155 					print_msg(quest_ptr[dval - 1]);
156 					dbgprintf("[A:");
157 					print_msg(ans_ptr[dval - 1]);
158 				}
159 				break;
160 			case AGT_MSG: /* Message */
161 				if (dval > last_message || dval < 1 || msg_ptr == NULL)
162 					dbgprintf("ILLEGAL MESSAGE");
163 				else {
164 					dbgprintf("(Msg%d)", dval);
165 					if (!dbg_nomsg)
166 						print_msg(msg_ptr[dval - 1]);
167 				}
168 				break;
169 			case AGT_ERR: /* Message */
170 				if (dval > NUM_ERR || dval < 1 || err_ptr == NULL)
171 					dbgprintf("ILLEGAL MESSAGE");
172 				else {
173 					dbgprintf("(Std%d)", dval);
174 					if (!dbg_nomsg)
175 						print_msg(err_ptr[dval - 1]);
176 				}
177 				break;
178 			case AGT_STR: /* String */
179 				if (dval - 1 >= MAX_USTR || userstr == NULL)
180 					dbgprintf("ILLEGAL STRING");
181 				else
182 					dbgprintf("\nStr%d:%s", dval, userstr[dval]);
183 				break;
184 			case AGT_CNT: /* Counter */
185 				printval("Cnt", dval, dbgcntptr);
186 				break;
187 			case AGT_DIR: /* Direction */
188 				if (dval >= 1 && dval <= 13)
189 					dbgprintf("%s", exitname[dval - 1]);
190 				else dbgprintf("ILL_DIR(%d)", dval);
191 				break;
192 			case AGT_SUB: /* Subroutine */
193 				dbgprintf("Subroutine %d", dval);
194 				break;
195 			case AGT_PIC: /* Picture */
196 			case AGT_PIX:
197 				dbgprintf("Picture #%d", dval);
198 				break;
199 			case AGT_FONT: /* Font */
200 				dbgprintf("Font #%d", dval);
201 				break;
202 			case AGT_SONG:  /* Song */
203 				dbgprintf("Song #%d", dval);
204 				break;
205 			case AGT_OBJFLAG:
206 				dbgprintf("ObjFlag%d", dval);
207 				break;
208 			case AGT_OBJPROP:
209 				dbgprintf("ObjProp%d", dval);
210 				break;
211 			case AGT_ATTR:
212 				if (dval < 0 || dval >= NUM_ATTR)
213 					dbgprintf("UnkownAttr%d", dval);
214 				else
215 					dbgprintf("%s", attrlist[dval].name);
216 				break;
217 			case AGT_PROP:
218 				if (dval < 0 || dval >= NUM_PROP)
219 					dbgprintf("UnknownProp%d", dval);
220 				else
221 					dbgprintf("%s", proplist[dval].name);
222 				break;
223 			case AGT_EXIT:
224 				if (dval >= exitmsg_base)
225 					argout(AGT_MSG, dval - exitmsg_base, 0);
226 				else
227 					argout(AGT_ROOM, dval, 0);
228 				break;
229 			default:
230 				dbgprintf("?+%d", dval);
231 			}
232 	}
233 	return 1;
234 }
235 
236 
debug_newline(integer op,rbool first_nl)237 void debug_newline(integer op, rbool first_nl) {
238 	rbool early_nl;
239 
240 	if (!dbg_nomsg) return;
241 	early_nl = (op == 1008 || op == 1027 || op == 1083 || op == 1105
242 	            || (op >= 1126 && op <= 1131));
243 	if (early_nl == first_nl)
244 		debugout("\n");
245 }
246 
247 
debug_cmd_out(int ip,integer op,int arg1,int arg2,int optype)248 void debug_cmd_out(int ip, integer op, int arg1, int arg2, int optype) {
249 	int j;
250 	const opdef *opdata;
251 	rbool save_dbg_nomsg;
252 
253 	dbgprintf("  %2d:", ip);
254 	save_dbg_nomsg = 0; /* Just to silence compiler warnings. */
255 
256 	opdata = get_opdef(op);
257 	if (opdata == &illegal_def)
258 		dbgprintf("ILLEGAL %d\n", op);
259 	else {
260 		if (op >= END_ACT) dbgprintf("!"); /* "Terminal" Actions */
261 		else if (op <= MAX_COND) dbgprintf("?"); /* Condition */
262 		if (op == 1063) { /* RandomMessage needs special handling */
263 			save_dbg_nomsg = dbg_nomsg;
264 			dbg_nomsg = 1;
265 		}
266 		dbgprintf("%s", opdata->opcode);
267 		for (j = 0; j < opdata->argnum; j++) {
268 			dbgprintf("\t");
269 			argout(j == 0 ? opdata->arg1 : opdata->arg2 , j == 0 ? arg1 : arg2,
270 			       optype >> 2);
271 			optype <<= 2;
272 		}
273 		if (op == 1063)
274 			dbg_nomsg = save_dbg_nomsg;
275 	}
276 	debug_newline(op, 1);
277 }
278 
279 
debug_head(int i)280 void debug_head(int i) {
281 	int v, w, a;
282 
283 	v = verb_code(command[i].verbcmd);
284 	if (v >= BASE_VERB && v < BASE_VERB + DUMB_VERB && syntbl[synlist[v]] != 0)
285 		w = syntbl[synlist[v]];
286 	else w = command[i].verbcmd;
287 	if (command[i].actor > 0) {
288 		dbgprintf("CMD %d: ", i);
289 		a = command[i].actor;
290 	} else {
291 		dbgprintf("REDIR: ");
292 		a = -command[i].actor;
293 	}
294 
295 	if (a == 2)
296 		dbgprintf("anybody, ");
297 	else if (a > 2) {
298 		char *name;
299 		name = objname(a);
300 		name[0] = toupper(name[0]);
301 		dbgprintf("%s, ", name);
302 		rfree(name);
303 	}
304 
305 	dbgprintf("%s ", w == 0 ? "any" : dict[w]);
306 	if (command[i].noun_adj != 0)
307 		dbgprintf("%s ", gdict(command[i].noun_adj));
308 	dbgprintf("%s %s ", gdict(command[i].nouncmd),
309 	          (ver == 3) ? gdict(command[i].prep) : "->");
310 	if (command[i].obj_adj != 0)
311 		dbgprintf("%s ", gdict(command[i].obj_adj));
312 	dbgprintf("%s\n", gdict(command[i].objcmd));
313 
314 }
315 
316 } // End of namespace AGT
317 } // End of namespace Glk
318