comparison debug.c @ 524:fb39534b6604

Move debugging code outside of main source file
author Mike Pavone <pavone@retrodev.com>
date Tue, 11 Feb 2014 21:53:31 -0800
parents
children 62860044337d
comparison
equal deleted inserted replaced
523:450c7745379a 524:fb39534b6604
1 #include "debug.h"
2 #include "blastem.h"
3 #include "68kinst.h"
4 #include <stdlib.h>
5 #include <string.h>
6
7 bp_def * breakpoints = NULL;
8 bp_def * zbreakpoints = NULL;
9 uint32_t bp_index = 0;
10 uint32_t zbp_index = 0;
11
12 bp_def ** find_breakpoint(bp_def ** cur, uint32_t address)
13 {
14 while (*cur) {
15 if ((*cur)->address == address) {
16 break;
17 }
18 cur = &((*cur)->next);
19 }
20 return cur;
21 }
22
23 bp_def ** find_breakpoint_idx(bp_def ** cur, uint32_t index)
24 {
25 while (*cur) {
26 if ((*cur)->index == index) {
27 break;
28 }
29 cur = &((*cur)->next);
30 }
31 return cur;
32 }
33
34 disp_def * displays = NULL;
35 disp_def * zdisplays = NULL;
36 uint32_t disp_index = 0;
37 uint32_t zdisp_index = 0;
38
39 void add_display(disp_def ** head, uint32_t *index, char format_char, char * param)
40 {
41 disp_def * ndisp = malloc(sizeof(*ndisp));
42 ndisp->format_char = format_char;
43 ndisp->param = strdup(param);
44 ndisp->next = *head;
45 ndisp->index = *index++;
46 *head = ndisp;
47 }
48
49 void remove_display(disp_def ** head, uint32_t index)
50 {
51 while (*head) {
52 if ((*head)->index == index) {
53 disp_def * del_disp = *head;
54 *head = del_disp->next;
55 free(del_disp->param);
56 free(del_disp);
57 } else {
58 head = &(*head)->next;
59 }
60 }
61 }
62
63 char * find_param(char * buf)
64 {
65 for (; *buf; buf++) {
66 if (*buf == ' ') {
67 if (*(buf+1)) {
68 return buf+1;
69 }
70 }
71 }
72 return NULL;
73 }
74
75 void strip_nl(char * buf)
76 {
77 for(; *buf; buf++) {
78 if (*buf == '\n') {
79 *buf = 0;
80 return;
81 }
82 }
83 }
84
85 void zdebugger_print(z80_context * context, char format_char, char * param)
86 {
87 uint32_t value;
88 char format[8];
89 strcpy(format, "%s: %d\n");
90 switch (format_char)
91 {
92 case 'x':
93 case 'X':
94 case 'd':
95 case 'c':
96 format[5] = format_char;
97 break;
98 case '\0':
99 break;
100 default:
101 fprintf(stderr, "Unrecognized format character: %c\n", format_char);
102 }
103 switch (param[0])
104 {
105 case 'a':
106 if (param[1] == 'f') {
107 if(param[2] == '\'') {
108 value = context->alt_regs[Z80_A] << 8;
109 value |= context->alt_flags[ZF_S] << 7;
110 value |= context->alt_flags[ZF_Z] << 6;
111 value |= context->alt_flags[ZF_H] << 4;
112 value |= context->alt_flags[ZF_PV] << 2;
113 value |= context->alt_flags[ZF_N] << 1;
114 value |= context->alt_flags[ZF_C];
115 } else {
116 value = context->regs[Z80_A] << 8;
117 value |= context->flags[ZF_S] << 7;
118 value |= context->flags[ZF_Z] << 6;
119 value |= context->flags[ZF_H] << 4;
120 value |= context->flags[ZF_PV] << 2;
121 value |= context->flags[ZF_N] << 1;
122 value |= context->flags[ZF_C];
123 }
124 } else if(param[1] == '\'') {
125 value = context->alt_regs[Z80_A];
126 } else {
127 value = context->regs[Z80_A];
128 }
129 break;
130 case 'b':
131 if (param[1] == 'c') {
132 if(param[2] == '\'') {
133 value = context->alt_regs[Z80_B] << 8;
134 value |= context->alt_regs[Z80_C];
135 } else {
136 value = context->regs[Z80_B] << 8;
137 value |= context->regs[Z80_C];
138 }
139 } else if(param[1] == '\'') {
140 value = context->alt_regs[Z80_B];
141 } else if(param[1] == 'a') {
142 value = context->bank_reg << 15;
143 } else {
144 value = context->regs[Z80_B];
145 }
146 break;
147 case 'c':
148 if(param[1] == '\'') {
149 value = context->alt_regs[Z80_C];
150 } else if(param[1] == 'y') {
151 value = context->current_cycle;
152 } else {
153 value = context->regs[Z80_C];
154 }
155 break;
156 case 'd':
157 if (param[1] == 'e') {
158 if(param[2] == '\'') {
159 value = context->alt_regs[Z80_D] << 8;
160 value |= context->alt_regs[Z80_E];
161 } else {
162 value = context->regs[Z80_D] << 8;
163 value |= context->regs[Z80_E];
164 }
165 } else if(param[1] == '\'') {
166 value = context->alt_regs[Z80_D];
167 } else {
168 value = context->regs[Z80_D];
169 }
170 break;
171 case 'e':
172 if(param[1] == '\'') {
173 value = context->alt_regs[Z80_E];
174 } else {
175 value = context->regs[Z80_E];
176 }
177 break;
178 case 'f':
179 if(param[2] == '\'') {
180 value = context->alt_flags[ZF_S] << 7;
181 value |= context->alt_flags[ZF_Z] << 6;
182 value |= context->alt_flags[ZF_H] << 4;
183 value |= context->alt_flags[ZF_PV] << 2;
184 value |= context->alt_flags[ZF_N] << 1;
185 value |= context->alt_flags[ZF_C];
186 } else {
187 value = context->flags[ZF_S] << 7;
188 value |= context->flags[ZF_Z] << 6;
189 value |= context->flags[ZF_H] << 4;
190 value |= context->flags[ZF_PV] << 2;
191 value |= context->flags[ZF_N] << 1;
192 value |= context->flags[ZF_C];
193 }
194 break;
195 case 'h':
196 if (param[1] == 'l') {
197 if(param[2] == '\'') {
198 value = context->alt_regs[Z80_H] << 8;
199 value |= context->alt_regs[Z80_L];
200 } else {
201 value = context->regs[Z80_H] << 8;
202 value |= context->regs[Z80_L];
203 }
204 } else if(param[1] == '\'') {
205 value = context->alt_regs[Z80_H];
206 } else {
207 value = context->regs[Z80_H];
208 }
209 break;
210 case 'l':
211 if(param[1] == '\'') {
212 value = context->alt_regs[Z80_L];
213 } else {
214 value = context->regs[Z80_L];
215 }
216 break;
217 case 'i':
218 if(param[1] == 'x') {
219 if (param[2] == 'h') {
220 value = context->regs[Z80_IXH];
221 } else if(param[2] == 'l') {
222 value = context->regs[Z80_IXL];
223 } else {
224 value = context->regs[Z80_IXH] << 8;
225 value |= context->regs[Z80_IXL];
226 }
227 } else if(param[1] == 'y') {
228 if (param[2] == 'h') {
229 value = context->regs[Z80_IYH];
230 } else if(param[2] == 'l') {
231 value = context->regs[Z80_IYL];
232 } else {
233 value = context->regs[Z80_IYH] << 8;
234 value |= context->regs[Z80_IYL];
235 }
236 } else if(param[1] == 'n') {
237 value = context->int_cycle;
238 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '1') {
239 value = context->iff1;
240 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '2') {
241 value = context->iff2;
242 } else {
243 value = context->im;
244 }
245 break;
246 case 's':
247 if (param[1] == 'p') {
248 value = context->sp;
249 }
250 break;
251 case '0':
252 if (param[1] == 'x') {
253 uint16_t p_addr = strtol(param+2, NULL, 16);
254 if (p_addr < 0x4000) {
255 value = z80_ram[p_addr & 0x1FFF];
256 } else if(p_addr >= 0x8000) {
257 uint32_t v_addr = context->bank_reg << 15;
258 v_addr += p_addr & 0x7FFF;
259 if (v_addr < 0x400000) {
260 value = cart[v_addr/2];
261 } else if(v_addr > 0xE00000) {
262 value = ram[(v_addr & 0xFFFF)/2];
263 }
264 if (v_addr & 1) {
265 value &= 0xFF;
266 } else {
267 value >>= 8;
268 }
269 }
270 }
271 break;
272 }
273 printf(format, param, value);
274 }
275
276 z80_context * zdebugger(z80_context * context, uint16_t address)
277 {
278 static char last_cmd[1024];
279 char input_buf[1024];
280 static uint16_t branch_t;
281 static uint16_t branch_f;
282 z80inst inst;
283 //Check if this is a user set breakpoint, or just a temporary one
284 bp_def ** this_bp = find_breakpoint(&zbreakpoints, address);
285 if (*this_bp) {
286 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index);
287 } else {
288 zremove_breakpoint(context, address);
289 }
290 uint8_t * pc;
291 if (address < 0x4000) {
292 pc = z80_ram + (address & 0x1FFF);
293 } else if (address >= 0x8000) {
294 if (context->bank_reg < (0x400000 >> 15)) {
295 fprintf(stderr, "Entered Z80 debugger in banked memory address %X, which is not yet supported\n", address);
296 exit(1);
297 } else {
298 fprintf(stderr, "Entered Z80 debugger in banked memory address %X, but the bank is not pointed to a cartridge address\n", address);
299 exit(1);
300 }
301 } else {
302 fprintf(stderr, "Entered Z80 debugger at address %X\n", address);
303 exit(1);
304 }
305 for (disp_def * cur = zdisplays; cur; cur = cur->next) {
306 zdebugger_print(context, cur->format_char, cur->param);
307 }
308 uint8_t * after_pc = z80_decode(pc, &inst);
309 z80_disasm(&inst, input_buf, address);
310 printf("%X:\t%s\n", address, input_buf);
311 uint16_t after = address + (after_pc-pc);
312 int debugging = 1;
313 while(debugging) {
314 fputs(">", stdout);
315 if (!fgets(input_buf, sizeof(input_buf), stdin)) {
316 fputs("fgets failed", stderr);
317 break;
318 }
319 strip_nl(input_buf);
320 //hitting enter repeats last command
321 if (input_buf[0]) {
322 strcpy(last_cmd, input_buf);
323 } else {
324 strcpy(input_buf, last_cmd);
325 }
326 char * param;
327 char format[8];
328 uint32_t value;
329 bp_def * new_bp;
330 switch(input_buf[0])
331 {
332 case 'a':
333 param = find_param(input_buf);
334 if (!param) {
335 fputs("a command requires a parameter\n", stderr);
336 break;
337 }
338 value = strtol(param, NULL, 16);
339 zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
340 debugging = 0;
341 break;
342 case 'b':
343 param = find_param(input_buf);
344 if (!param) {
345 fputs("b command requires a parameter\n", stderr);
346 break;
347 }
348 value = strtol(param, NULL, 16);
349 zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
350 new_bp = malloc(sizeof(bp_def));
351 new_bp->next = zbreakpoints;
352 new_bp->address = value;
353 new_bp->index = zbp_index++;
354 zbreakpoints = new_bp;
355 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
356 break;
357 case 'c':
358 puts("Continuing");
359 debugging = 0;
360 break;
361 case 'd':
362 if (input_buf[1] == 'i') {
363 char format_char = 0;
364 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
365 if (input_buf[i] == '/') {
366 format_char = input_buf[i+1];
367 break;
368 }
369 }
370 param = find_param(input_buf);
371 if (!param) {
372 fputs("display command requires a parameter\n", stderr);
373 break;
374 }
375 zdebugger_print(context, format_char, param);
376 add_display(&zdisplays, &zdisp_index, format_char, param);
377 } else if (input_buf[1] == 'e' || input_buf[1] == ' ') {
378 param = find_param(input_buf);
379 if (!param) {
380 fputs("delete command requires a parameter\n", stderr);
381 break;
382 }
383 if (param[0] >= '0' && param[0] <= '9') {
384 value = atoi(param);
385 this_bp = find_breakpoint_idx(&zbreakpoints, value);
386 if (!*this_bp) {
387 fprintf(stderr, "Breakpoint %d does not exist\n", value);
388 break;
389 }
390 new_bp = *this_bp;
391 zremove_breakpoint(context, new_bp->address);
392 *this_bp = new_bp->next;
393 free(new_bp);
394 } else if (param[0] == 'd') {
395 param = find_param(param);
396 if (!param) {
397 fputs("delete display command requires a parameter\n", stderr);
398 break;
399 }
400 remove_display(&zdisplays, atoi(param));
401 }
402 }
403 break;
404 case 'n':
405 //TODO: Handle conditional branch instructions
406 if (inst.op == Z80_JP) {
407 if (inst.addr_mode == Z80_IMMED) {
408 after = inst.immed;
409 } else if (inst.ea_reg == Z80_HL) {
410 after = context->regs[Z80_H] << 8 | context->regs[Z80_L];
411 } else if (inst.ea_reg == Z80_IX) {
412 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
413 } else if (inst.ea_reg == Z80_IY) {
414 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
415 }
416 } else if(inst.op == Z80_JR) {
417 after += inst.immed;
418 } else if(inst.op == Z80_RET) {
419 if (context->sp < 0x4000) {
420 after = z80_ram[context->sp & 0x1FFF] | z80_ram[(context->sp+1) & 0x1FFF] << 8;
421 }
422 }
423 zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
424 debugging = 0;
425 break;
426 case 'p':
427 param = find_param(input_buf);
428 if (!param) {
429 fputs("p command requires a parameter\n", stderr);
430 break;
431 }
432 zdebugger_print(context, input_buf[1] == '/' ? input_buf[2] : 0, param);
433 break;
434 case 'q':
435 puts("Quitting");
436 exit(0);
437 break;
438 case 's': {
439 param = find_param(input_buf);
440 if (!param) {
441 fputs("s command requires a file name\n", stderr);
442 break;
443 }
444 FILE * f = fopen(param, "wb");
445 if (f) {
446 if(fwrite(z80_ram, 1, sizeof(z80_ram), f) != sizeof(z80_ram)) {
447 fputs("Error writing file\n", stderr);
448 }
449 fclose(f);
450 } else {
451 fprintf(stderr, "Could not open %s for writing\n", param);
452 }
453 break;
454 }
455 default:
456 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
457 break;
458 }
459 }
460 return context;
461 }
462
463 m68k_context * debugger(m68k_context * context, uint32_t address)
464 {
465 static char last_cmd[1024];
466 char input_buf[1024];
467 static uint32_t branch_t;
468 static uint32_t branch_f;
469 m68kinst inst;
470 //probably not necessary, but let's play it safe
471 address &= 0xFFFFFF;
472 if (address == branch_t) {
473 bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f);
474 if (!*f_bp) {
475 remove_breakpoint(context, branch_f);
476 }
477 branch_t = branch_f = 0;
478 } else if(address == branch_f) {
479 bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t);
480 if (!*t_bp) {
481 remove_breakpoint(context, branch_t);
482 }
483 branch_t = branch_f = 0;
484 }
485 //Check if this is a user set breakpoint, or just a temporary one
486 bp_def ** this_bp = find_breakpoint(&breakpoints, address);
487 if (*this_bp) {
488 printf("68K Breakpoint %d hit\n", (*this_bp)->index);
489 } else {
490 remove_breakpoint(context, address);
491 }
492 uint16_t * pc;
493 if (address < 0x400000) {
494 pc = cart + address/2;
495 } else if(address > 0xE00000) {
496 pc = ram + (address & 0xFFFF)/2;
497 } else {
498 fprintf(stderr, "Entered 68K debugger at address %X\n", address);
499 exit(1);
500 }
501 uint16_t * after_pc = m68k_decode(pc, &inst, address);
502 m68k_disasm(&inst, input_buf);
503 printf("%X: %s\n", address, input_buf);
504 uint32_t after = address + (after_pc-pc)*2;
505 int debugging = 1;
506 while (debugging) {
507 fputs(">", stdout);
508 if (!fgets(input_buf, sizeof(input_buf), stdin)) {
509 fputs("fgets failed", stderr);
510 break;
511 }
512 strip_nl(input_buf);
513 //hitting enter repeats last command
514 if (input_buf[0]) {
515 strcpy(last_cmd, input_buf);
516 } else {
517 strcpy(input_buf, last_cmd);
518 }
519 char * param;
520 char format[8];
521 uint32_t value;
522 bp_def * new_bp;
523 switch(input_buf[0])
524 {
525 case 'c':
526 puts("Continuing");
527 debugging = 0;
528 break;
529 case 'b':
530 param = find_param(input_buf);
531 if (!param) {
532 fputs("b command requires a parameter\n", stderr);
533 break;
534 }
535 value = strtol(param, NULL, 16);
536 insert_breakpoint(context, value, (uint8_t *)debugger);
537 new_bp = malloc(sizeof(bp_def));
538 new_bp->next = breakpoints;
539 new_bp->address = value;
540 new_bp->index = bp_index++;
541 breakpoints = new_bp;
542 printf("68K Breakpoint %d set at %X\n", new_bp->index, value);
543 break;
544 case 'a':
545 param = find_param(input_buf);
546 if (!param) {
547 fputs("a command requires a parameter\n", stderr);
548 break;
549 }
550 value = strtol(param, NULL, 16);
551 insert_breakpoint(context, value, (uint8_t *)debugger);
552 debugging = 0;
553 break;
554 case 'd':
555 param = find_param(input_buf);
556 if (!param) {
557 fputs("d command requires a parameter\n", stderr);
558 break;
559 }
560 value = atoi(param);
561 this_bp = find_breakpoint_idx(&breakpoints, value);
562 if (!*this_bp) {
563 fprintf(stderr, "Breakpoint %d does not exist\n", value);
564 break;
565 }
566 new_bp = *this_bp;
567 *this_bp = (*this_bp)->next;
568 free(new_bp);
569 break;
570 case 'p':
571 strcpy(format, "%s: %d\n");
572 if (input_buf[1] == '/') {
573 switch (input_buf[2])
574 {
575 case 'x':
576 case 'X':
577 case 'd':
578 case 'c':
579 format[5] = input_buf[2];
580 break;
581 default:
582 fprintf(stderr, "Unrecognized format character: %c\n", input_buf[2]);
583 }
584 }
585 param = find_param(input_buf);
586 if (!param) {
587 fputs("p command requires a parameter\n", stderr);
588 break;
589 }
590 if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') {
591 value = context->dregs[param[1]-'0'];
592 } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') {
593 value = context->aregs[param[1]-'0'];
594 } else if (param[0] == 'S' && param[1] == 'R') {
595 value = (context->status << 8);
596 for (int flag = 0; flag < 5; flag++) {
597 value |= context->flags[flag] << (4-flag);
598 }
599 } else if(param[0] == 'c') {
600 value = context->current_cycle;
601 } else if (param[0] == '0' && param[1] == 'x') {
602 uint32_t p_addr = strtol(param+2, NULL, 16);
603 value = read_dma_value(p_addr/2);
604 } else {
605 fprintf(stderr, "Unrecognized parameter to p: %s\n", param);
606 break;
607 }
608 printf(format, param, value);
609 break;
610 case 'n':
611 if (inst.op == M68K_RTS) {
612 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
613 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
614 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
615 } else if(m68k_is_noncall_branch(&inst)) {
616 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
617 branch_f = after;
618 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
619 insert_breakpoint(context, branch_t, (uint8_t *)debugger);
620 } else if(inst.op == M68K_DBCC) {
621 if ( inst.extra.cond == COND_FALSE) {
622 if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
623 after = m68k_branch_target(&inst, context->dregs, context->aregs);
624 }
625 } else {
626 branch_t = after;
627 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
628 insert_breakpoint(context, branch_f, (uint8_t *)debugger);
629 }
630 } else {
631 after = m68k_branch_target(&inst, context->dregs, context->aregs);
632 }
633 }
634 insert_breakpoint(context, after, (uint8_t *)debugger);
635 debugging = 0;
636 break;
637 case 'o':
638 if (inst.op == M68K_RTS) {
639 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
640 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
641 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
642 } else if(m68k_is_noncall_branch(&inst)) {
643 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
644 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
645 if (branch_t < after) {
646 branch_t = 0;
647 } else {
648 branch_f = after;
649 insert_breakpoint(context, branch_t, (uint8_t *)debugger);
650 }
651 } else if(inst.op == M68K_DBCC) {
652 uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
653 if (target > after) {
654 if (inst.extra.cond == COND_FALSE) {
655 after = target;
656 } else {
657 branch_f = target;
658 branch_t = after;
659 insert_breakpoint(context, branch_f, (uint8_t *)debugger);
660 }
661 }
662 } else {
663 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
664 }
665 }
666 insert_breakpoint(context, after, (uint8_t *)debugger);
667 debugging = 0;
668 break;
669 case 's':
670 if (inst.op == M68K_RTS) {
671 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
672 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
673 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
674 } else if(m68k_is_branch(&inst)) {
675 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
676 branch_f = after;
677 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
678 insert_breakpoint(context, branch_t, (uint8_t *)debugger);
679 } else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) {
680 branch_t = after;
681 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
682 insert_breakpoint(context, branch_f, (uint8_t *)debugger);
683 } else {
684 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
685 }
686 }
687 insert_breakpoint(context, after, (uint8_t *)debugger);
688 debugging = 0;
689 break;
690 case 'v': {
691 genesis_context * gen = context->system;
692 //VDP debug commands
693 switch(input_buf[1])
694 {
695 case 's':
696 vdp_print_sprite_table(gen->vdp);
697 break;
698 case 'r':
699 vdp_print_reg_explain(gen->vdp);
700 break;
701 }
702 break;
703 }
704 case 'z': {
705 genesis_context * gen = context->system;
706 //Z80 debug commands
707 switch(input_buf[1])
708 {
709 case 'b':
710 param = find_param(input_buf);
711 if (!param) {
712 fputs("zb command requires a parameter\n", stderr);
713 break;
714 }
715 value = strtol(param, NULL, 16);
716 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger);
717 new_bp = malloc(sizeof(bp_def));
718 new_bp->next = zbreakpoints;
719 new_bp->address = value;
720 new_bp->index = zbp_index++;
721 zbreakpoints = new_bp;
722 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
723 break;
724 case 'p':
725 param = find_param(input_buf);
726 if (!param) {
727 fputs("zp command requires a parameter\n", stderr);
728 break;
729 }
730 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param);
731 }
732 break;
733 }
734 case 'q':
735 puts("Quitting");
736 exit(0);
737 break;
738 default:
739 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
740 break;
741 }
742 }
743 return context;
744 }