Mercurial > repos > blastem
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) { |