1 
2 /*
3  *   O2EM Free Odyssey2 / Videopac+ Emulator
4  *
5  *   Created by Daniel Boris <dboris@comcast.net>  (c) 1997,1998
6  *
7  *   Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
8  *
9  *   http://o2em.sourceforge.net
10  *
11  *
12  *
13  *   O2EM built-in debugger
14  */
15 
16 
17 #include <stdio.h>
18 #include <string.h>
19 #include "cpu.h"
20 #include "keyboard.h"
21 #include "vmachine.h"
22 #include "audio.h"
23 #include "vdc.h"
24 #include "table.h"
25 #include "debug.h"
26 #include "allegro.h"
27 
28 #if defined(ALLEGRO_WINDOWS)
29 #include "winalleg.h"
30 #include <conio.h>
31 #define KBHIT _kbhit
32 #elif defined(ALLEGRO_DOS)
33 #include <conio.h>
34 #define KBHIT kbhit
35 #else
36 #define KBHIT() 0
37 #endif
38 
39 static int disasm(ADDRESS p);
40 static void show_reg(void);
41 
42 
debug(void)43 void debug(void) {
44 	int done,i,go,j;
45 	char inp[80];
46 	char *tok;
47 	ADDRESS ad,run_to;
48 	char cr[2],ff[2];
49 	Byte d,a;
50 
51 	dbstick1=dbstick2=0;
52 	cr[0]=13;
53 	cr[1]=0;
54 	ff[0]=0x0c;
55 	ff[1]=0;
56 
57 	done=go=0;
58 
59 	set_display_switch_mode(SWITCH_BACKGROUND);
60 
61 	if (sndlog) fclose(sndlog);
62 
63 	#ifdef ALLEGRO_WINDOWS
64 	FreeConsole();
65 	AllocConsole();
66 	#endif
67 
68 	printf("\nDebug mode\n\n");
69 
70 	while (!done) {
71 		while (go > 0) {
72 			disasm(pc);
73 			cpu_exec();
74 			go--;
75 			if (KBHIT()) {
76 				go=0;
77 				disasm(pc);
78 				show_reg();
79 				cpu_exec();
80 
81 			}
82 		}
83 		printf("> ");
84 		fgets(inp,76,stdin);
85 		if ((strlen(inp)>0) && (inp[strlen(inp)-1]=='\n')) inp[strlen(inp)-1]=0;
86 		strlwr(inp);
87 		strcat(inp," \n");
88 		tok=strtok(inp," ");
89 		if (!tok) tok="";
90 		if (!strcmp(tok,"h") || !strcmp(tok,"?") || !strcmp(tok,"help")) {
91 			printf("display - show display\n");
92 			#ifdef ALLEGRO_DOS
93 			printf("cls - clear screen\n");
94 			#endif
95 			printf("clrkey - clear keypresses\n");
96 			printf("setkey n - set key n pressed\n");
97 			printf("s - step\n");
98 			printf("reg - display registers\n");
99 			printf("stack - display stack\n");
100 			printf("video - display VDC registers\n");
101 			printf("exram - display external RAM contents\n");
102 			printf("run # - run to address #\n");
103 			printf("runvb - run to VBL\n");
104 			printf("runnvb - run to no VBL\n");
105 			printf("go # - execute # instructions\n");
106 			printf("intram - display internal ram\n");
107 			printf("di # - disassemble memory #\n");
108 			printf("md # - display memory #\n");
109 			printf("wvdc a d - write data d to VDC address a\n");
110 			printf("col - display collision table\n");
111 			printf("stick1 # - set stick1 to #\n");
112 			printf("stick2 # - set stick2 to #\n");
113 			printf("sndlog [file] - log raw sound to file\n");
114 			printf("showfps - display the number of frames per second\n");
115 			printf("q - quit debugger and return to emulation\n");
116 			printf("\n");
117 		} else if (!strcmp(tok,"display")) {
118 			grmode();
119 			clip_low = 0;
120 			clip_high = 85000;
121 			draw_display();
122 			finish_display();
123 			init_keyboard();
124 			do {
125 				rest(1);
126 			} while((key_done==0) && (!keypressed()));
127 			set_textmode();
128 			set_display_switch_mode(SWITCH_BACKGROUND);
129 		} else if (!strcmp(tok,"cls")) {
130 			#ifdef ALLEGRO_DOS
131 			clrscr();
132 			#endif
133 		} else if (!strcmp(tok,"clrkey")) {
134 			for(i=0; i<128; i++) key2[i]=0;
135 		} else if (!strcmp(tok,"setkey")) {
136 			tok=strtok(NULL," ");
137 			if (tok){
138 				sscanf(tok,"%d",&i);
139 				if ((i>0) && (i<128)){
140 					printf("Key %d set to pressed\n",i);
141 					key2[i]=1;
142 				}
143 				key2vcnt=0;
144 			}
145 		} else if (!strcmp(tok,"stick1")) {
146 			tok=strtok(NULL," ");
147 			if (tok) {
148 				i=0;
149 				sscanf(tok,"%x",&i);
150 				printf("Stick 1 set to %d\n",i);
151 				dbstick1=i;
152 				key2vcnt=0;
153 			}
154 		} else if (!strcmp(tok,"stick2")) {
155 			tok=strtok(NULL," ");
156 			if (tok) {
157 				i=0;
158 				sscanf(tok,"%x",&i);
159 				printf("Stick 2 set to %d\n",i);
160 				dbstick2=i;
161 				key2vcnt=0;
162 			}
163 		} else if (!strcmp(tok,"s")) {
164 			disasm(pc);
165 			show_reg();
166 			cpu_exec();
167 		} else if (!strcmp(tok,"reg")) {
168 			show_reg();
169 		} else if (!strcmp(tok,"stack")) {
170 			for(i=8; i<24; i+=2) {
171 				ad = intRAM[i];
172 				d = intRAM[i+1];
173 				ad = ad | ((d & 0x0F) << 8);
174 				printf("%x: PC=%x PSW=%x",i,ad,d);
175 				if (i == sp) printf(" <<SP");
176 				printf("\n");
177 			}
178 			printf("\n");
179 		} else if (!strcmp(tok,"q")) {
180 			printf("\nReturning to emulation\n\n");
181 			done=1;
182 		} else if (!strcmp(tok,"pvideo")) {
183 			j=0;
184 			fprintf(stderr,"%02x:",0);
185 			for(i=0; i<256; i++) {
186 				fprintf(stderr,"%02x,",VDCwrite[i]);
187 				j++;
188 				if (j == 16) {
189 					fprintf(stderr,"%s\n",cr);
190 					fprintf(stderr,"%02x:",i+1);
191 					j=0;
192 				}
193 			}
194 			fprintf(stderr,"%s\n",cr);
195 			fprintf(stderr,"%s",ff);
196 		} else if (!strcmp(tok,"video")) {
197 			j=0;
198 			printf("%02x:",0);
199 			for(i=0; i<256; i++) {
200 				printf("%02x",VDCwrite[i]);
201 				if (j < 15) printf(",");
202 				j++;
203 				if (j == 16 && i != 255) {
204 					printf("\n");
205 					printf("%02x:",i+1);
206 					j=0;
207 				}
208 			}
209 			printf("\n");
210 		} else if (!strcmp(tok,"keys")) {
211 			j=0;
212 			printf("%02x:",0);
213 			for(i=0; i<128; i++) {
214 				printf("%02x,",key2[i]);
215 				j++;
216 				if (j == 16) {
217 					printf("\n");
218 					printf("%02x:",i+1);
219 
220 					j=0;
221 				}
222 			}
223 			printf("\n");
224 		} else if (!strcmp(tok,"col")) {
225 			j=0;
226 			printf("%02x:",0);
227 			for(i=0; i<256; i++) {
228 				printf("%02x,",coltab[i]);
229 				j++;
230 				if (j == 16) {
231 					printf("\n");
232 					printf("%02x:",i+1);
233 					j=0;
234 				}
235 			}
236 			printf("\n");
237 			printf("Colreg: %x\n ",ext_read(0xA2));
238 		} else if (!strcmp(tok,"exram")) {
239 			j=0;
240 			printf("%02x:",0);
241 			for(i=0; i<256; i++) {
242 				printf("%02x",extRAM[i]);
243 				if (j < 15) printf(",");
244 				j++;
245 				if (j == 16 && i !=255) {
246 					printf("\n");
247 					printf("%02x:",i+1);
248 
249 					j=0;
250 				}
251 			}
252 			printf("\n\n");
253 		} else if (!strcmp(tok,"intram")) {
254 			j=0;
255 			printf("%02x:",0);
256 			for(i=0; i<64; i++) {
257 				printf("%02x",intRAM[i]);
258 				if (j < 15) printf(",");
259 				j++;
260 				if (j == 16 && i != 63) {
261 					printf("\n");
262 					printf("%02x:",i+1);
263 					j=0;
264 				}
265 			}
266 			printf("\n\n");
267 		} else if (!strcmp(tok,"run")) {
268 			tok=strtok(NULL," ");
269 			if (tok){
270 				sscanf(tok,"%hx",&run_to);
271 				printf("Run to %x\n",run_to);
272 				while (pc != run_to) {
273 					cpu_exec();
274 					if (KBHIT()) break;
275 				}
276 				disasm(pc);
277 				show_reg();
278 				cpu_exec();
279 			}
280 		} else if (!strcmp(tok,"runvb")) {
281 			printf("Run to VBL\n");
282 			while (master_clk < 5500) {
283 				cpu_exec();
284 				if (KBHIT()) break;
285 			}
286 			disasm(pc);
287 			show_reg();
288 			cpu_exec();
289 		} else if (!strcmp(tok,"runnvb")) {
290 			printf("Run to no VBL\n");
291 			while (master_clk > 5500) {
292 				cpu_exec();
293 				if (KBHIT()) break;
294 			}
295 			disasm(pc);
296 			show_reg();
297 			cpu_exec();
298 		} else if (!strcmp(tok,"wvdc")) {
299 			int t;
300 			tok=strtok(NULL," ");
301 			if (tok){
302 				sscanf(tok,"%x",&t);
303 				a = (Byte)t;
304 				tok=strtok(NULL," ");
305 				if (tok){
306 					sscanf(tok,"%x",&t);
307 					d = (Byte)t;
308 					VDCwrite[a] = d;
309 				}
310 			}
311 		} else if (!strcmp(tok,"go")) {
312 			tok=strtok(NULL," ");
313 			if (tok) sscanf(tok,"%d",&go);
314 		} else if (!strcmp(tok,"di")) {
315 			tok=strtok(NULL," ");
316 			if (tok){
317 				ad=0;
318 				sscanf(tok,"%hx",&ad);
319 				if (ad<5100) {
320 					for(i=0; i<20; i++) {
321 						ad = ad + disasm(ad);
322 					}
323 				}
324 				printf("\n");
325 			}
326 		} else if (!strcmp(tok,"md")) {
327 			tok=strtok(NULL," ");
328 			if (tok){
329 				sscanf(tok,"%hx",&ad);
330 				printf("\n");
331 
332 				for (j=0; j<10; j++){
333 					if (ad+j*16<5100) {
334 						printf("%04x : ",ad+j*16);
335 						for (i=0; i<16; i++) printf("%02x ",rom[ad+j*16+i]);
336 						printf("\n");
337 					}
338 				}
339 				printf("\n\n");
340 			}
341 		} else if (!strcmp(tok,"sndlog")) {
342 			if (app_data.sound_en) {
343 				tok=strtok(NULL," ");
344 				if (tok){
345 					char file[80]="";
346 					sscanf(tok,"%79s",file);
347 					if (strlen(file)>0){
348 						sndlog = fopen(file,"wb");
349 						if (sndlog)
350 							printf("Sound log file created\n");
351 						else
352 							printf("Sound log file creation failed\n");
353 					}
354 				}
355 				printf("\n");
356 			} else printf("Sound emulation disabled\n\n");
357 		} else if (!strcmp(tok,"showfps")) {
358 			show_fps=1;
359 		} else if ((strlen(tok)>0) && (strcmp(tok,"\n"))) {
360 			printf("Unknown command\n\n");
361 		}
362 
363 	}
364 
365 	#ifdef ALLEGRO_WINDOWS
366 	FreeConsole();
367 	#endif
368 
369 }
370 
371 
show_reg(void)372 static void show_reg(void) {
373 	int i;
374 
375 		make_psw_debug();
376 		printf("PC: %04x  A: %02x PSW: %02x P1: %02x  P2: %02x",pc,acc,psw,p1,p2);
377 		printf("  clk: %d  reg:%d  count:%x  f:%x\n",master_clk,reg_pnt,itimer,frame);
378 		for (i=0; i<8; i++) {
379 			printf("R%d: %02x   R%d': %02x\n",i,intRAM[i],i,intRAM[i+24]);
380 		}
381 }
382 
383 
disasm(ADDRESS p)384 static int disasm(ADDRESS p) {
385 	Byte op,d;
386 	ADDRESS adr;
387 
388 	op=rom[p++];
389 	printf("%04x: %02x",p-1,op);
390 	if (lookup[op].bytes == 2) printf(",%02x",rom[p]);
391 	printf("  %s",lookup[op].mnemonic);
392 	switch(lookup[op].type) {
393 		case 0:
394 			printf("\n");
395 			break;
396 		case 1:
397 			d=rom[p];
398 			printf(" #%02x\n",d);
399 			break;
400 		case 2:
401 			adr=rom[p];
402 			adr = adr | ((op & 0xE0) << 3);
403 			printf(" $%03x\n",adr);
404 			break;
405 		case 3:
406 			printf(" $%02x\n",rom[p]);
407 			break;
408 	}
409 	return lookup[op].bytes;
410 }
411 
412