comparison debug.c @ 2104:ff32a90260c9

Initial support for using debugger on sub CPU
author Michael Pavone <pavone@retrodev.com>
date Fri, 11 Feb 2022 23:21:10 -0800
parents 8ee7ecbf3f21
children f80c6111e1ae
comparison
equal deleted inserted replaced
2103:522d04e2adcd 2104:ff32a90260c9
1 #include "debug.h" 1 #include "debug.h"
2 #include "genesis.h" 2 #include "genesis.h"
3 #include "68kinst.h" 3 #include "68kinst.h"
4 #include "segacd.h"
5 #include "blastem.h"
4 #include <stdlib.h> 6 #include <stdlib.h>
5 #include <string.h> 7 #include <string.h>
6 #ifndef _WIN32 8 #ifndef _WIN32
7 #include <sys/select.h> 9 #include <sys/select.h>
8 #endif 10 #endif
579 } 581 }
580 return context; 582 return context;
581 } 583 }
582 584
583 #endif 585 #endif
586
587 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after);
588 int run_genesis_debugger_command(m68k_context *context, uint32_t address, char *input_buf)
589 {
590 genesis_context * gen = context->system;
591 char *param;
592 uint32_t value;
593 bp_def *new_bp;
594 switch (input_buf[0])
595 {
596 case 'v':
597 //VDP debug commands
598 switch(input_buf[1])
599 {
600 case 's':
601 vdp_print_sprite_table(gen->vdp);
602 break;
603 case 'r':
604 vdp_print_reg_explain(gen->vdp);
605 break;
606 }
607 break;
608 case 'y':
609 //YM-2612 debug commands
610 switch(input_buf[1])
611 {
612 case 'c':
613 if (input_buf[2] == ' ') {
614 int channel = atoi(input_buf+3)-1;
615 ym_print_channel_info(gen->ym, channel);
616 } else {
617 for (int i = 0; i < 6; i++) {
618 ym_print_channel_info(gen->ym, i);
619 }
620 }
621 break;
622 case 't':
623 ym_print_timer_info(gen->ym);
624 break;
625 }
626 break;
627 case 'u':
628 if (gen->expansion) {
629 segacd_context *cd = gen->expansion;
630 if (input_buf[1]) {
631 //TODO: filter out commands that are unsafe to run when we don't have the current Sub CPU address
632 run_debugger_command(cd->m68k, 0, input_buf + 1, (m68kinst){}, 0);
633 } else {
634 cd->enter_debugger = 1;
635 return 0;
636 }
637 } else {
638 fputs("u command only valid when Sega/Mega CD is active\n", stderr);
639 }
640 break;
641 #ifndef NO_Z80
642 case 'z':
643 //Z80 debug commands
644 switch(input_buf[1])
645 {
646 case 'b':
647 param = find_param(input_buf);
648 if (!param) {
649 fputs("zb command requires a parameter\n", stderr);
650 break;
651 }
652 value = strtol(param, NULL, 16);
653 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger);
654 new_bp = malloc(sizeof(bp_def));
655 new_bp->next = zbreakpoints;
656 new_bp->address = value;
657 new_bp->index = zbp_index++;
658 zbreakpoints = new_bp;
659 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
660 break;
661 case 'p':
662 param = find_param(input_buf);
663 if (!param) {
664 fputs("zp command requires a parameter\n", stderr);
665 break;
666 }
667 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param);
668 }
669 break;
670 #endif
671 default:
672 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
673 break;
674 }
675 return 1;
676 }
584 677
585 static uint32_t branch_t; 678 static uint32_t branch_t;
586 static uint32_t branch_f; 679 static uint32_t branch_f;
587 680
588 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after) 681 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after)
878 } 971 }
879 } 972 }
880 insert_breakpoint(context, after, debugger); 973 insert_breakpoint(context, after, debugger);
881 return 0; 974 return 0;
882 } 975 }
883 case 'v': {
884 genesis_context * gen = context->system;
885 //VDP debug commands
886 switch(input_buf[1])
887 {
888 case 's':
889 vdp_print_sprite_table(gen->vdp);
890 break;
891 case 'r':
892 vdp_print_reg_explain(gen->vdp);
893 break;
894 }
895 break;
896 }
897 case 'y': {
898 genesis_context * gen = context->system;
899 //YM-2612 debug commands
900 switch(input_buf[1])
901 {
902 case 'c':
903 if (input_buf[2] == ' ') {
904 int channel = atoi(input_buf+3)-1;
905 ym_print_channel_info(gen->ym, channel);
906 } else {
907 for (int i = 0; i < 6; i++) {
908 ym_print_channel_info(gen->ym, i);
909 }
910 }
911 break;
912 case 't':
913 ym_print_timer_info(gen->ym);
914 break;
915 }
916 break;
917 }
918 #ifndef NO_Z80
919 case 'z': {
920 genesis_context * gen = context->system;
921 //Z80 debug commands
922 switch(input_buf[1])
923 {
924 case 'b':
925 param = find_param(input_buf);
926 if (!param) {
927 fputs("zb command requires a parameter\n", stderr);
928 break;
929 }
930 value = strtol(param, NULL, 16);
931 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger);
932 new_bp = malloc(sizeof(bp_def));
933 new_bp->next = zbreakpoints;
934 new_bp->address = value;
935 new_bp->index = zbp_index++;
936 zbreakpoints = new_bp;
937 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
938 break;
939 case 'p':
940 param = find_param(input_buf);
941 if (!param) {
942 fputs("zp command requires a parameter\n", stderr);
943 break;
944 }
945 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param);
946 }
947 break;
948 }
949 #endif
950 case '?': 976 case '?':
951 print_m68k_help(); 977 print_m68k_help();
952 break; 978 break;
953 case 'q': 979 case 'q':
954 puts("Quitting"); 980 puts("Quitting");
955 exit(0); 981 exit(0);
956 break; 982 break;
957 default: 983 default: {
958 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf); 984 if (context->system == current_system) {
959 break; 985 //primary 68K for current system
986 return run_genesis_debugger_command(context, address, input_buf);
987 } else {
988 //presumably Sega CD sub CPU
989 //TODO: consider making this more generic
990 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
991 }
992 break;
993 }
960 } 994 }
961 return 1; 995 return 1;
962 } 996 }
963 997
964 void print_m68k_help() 998 void print_m68k_help()
1011 m68kinst inst; 1045 m68kinst inst;
1012 1046
1013 init_terminal(); 1047 init_terminal();
1014 1048
1015 context->options->sync_components(context, 0); 1049 context->options->sync_components(context, 0);
1016 genesis_context *gen = context->system; 1050 if (context->system == current_system) {
1017 vdp_force_update_framebuffer(gen->vdp); 1051 genesis_context *gen = context->system;
1052 vdp_force_update_framebuffer(gen->vdp);
1053 }
1018 //probably not necessary, but let's play it safe 1054 //probably not necessary, but let's play it safe
1019 address &= 0xFFFFFF; 1055 address &= 0xFFFFFF;
1020 if (address == branch_t) { 1056 if (address == branch_t) {
1021 bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f); 1057 bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f);
1022 if (!*f_bp) { 1058 if (!*f_bp) {