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