Mercurial > repos > blastem
comparison blastem.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 | 0b21a1a73fb7 |
children | 6a648d944311 |
comparison
equal
deleted
inserted
replaced
523:450c7745379a | 524:fb39534b6604 |
---|---|
846 } | 846 } |
847 } | 847 } |
848 return context; | 848 return context; |
849 } | 849 } |
850 | 850 |
851 typedef struct bp_def { | |
852 struct bp_def * next; | |
853 uint32_t address; | |
854 uint32_t index; | |
855 } bp_def; | |
856 | |
857 bp_def * breakpoints = NULL; | |
858 bp_def * zbreakpoints = NULL; | |
859 uint32_t bp_index = 0; | |
860 uint32_t zbp_index = 0; | |
861 | |
862 bp_def ** find_breakpoint(bp_def ** cur, uint32_t address) | |
863 { | |
864 while (*cur) { | |
865 if ((*cur)->address == address) { | |
866 break; | |
867 } | |
868 cur = &((*cur)->next); | |
869 } | |
870 return cur; | |
871 } | |
872 | |
873 bp_def ** find_breakpoint_idx(bp_def ** cur, uint32_t index) | |
874 { | |
875 while (*cur) { | |
876 if ((*cur)->index == index) { | |
877 break; | |
878 } | |
879 cur = &((*cur)->next); | |
880 } | |
881 return cur; | |
882 } | |
883 | |
884 typedef struct disp_def { | |
885 struct disp_def * next; | |
886 char * param; | |
887 uint32_t index; | |
888 char format_char; | |
889 } disp_def; | |
890 | |
891 disp_def * displays = NULL; | |
892 disp_def * zdisplays = NULL; | |
893 uint32_t disp_index = 0; | |
894 uint32_t zdisp_index = 0; | |
895 | |
896 void add_display(disp_def ** head, uint32_t *index, char format_char, char * param) | |
897 { | |
898 disp_def * ndisp = malloc(sizeof(*ndisp)); | |
899 ndisp->format_char = format_char; | |
900 ndisp->param = strdup(param); | |
901 ndisp->next = *head; | |
902 ndisp->index = *index++; | |
903 *head = ndisp; | |
904 } | |
905 | |
906 void remove_display(disp_def ** head, uint32_t index) | |
907 { | |
908 while (*head) { | |
909 if ((*head)->index == index) { | |
910 disp_def * del_disp = *head; | |
911 *head = del_disp->next; | |
912 free(del_disp->param); | |
913 free(del_disp); | |
914 } else { | |
915 head = &(*head)->next; | |
916 } | |
917 } | |
918 } | |
919 | |
920 char * find_param(char * buf) | |
921 { | |
922 for (; *buf; buf++) { | |
923 if (*buf == ' ') { | |
924 if (*(buf+1)) { | |
925 return buf+1; | |
926 } | |
927 } | |
928 } | |
929 return NULL; | |
930 } | |
931 | |
932 void strip_nl(char * buf) | |
933 { | |
934 for(; *buf; buf++) { | |
935 if (*buf == '\n') { | |
936 *buf = 0; | |
937 return; | |
938 } | |
939 } | |
940 } | |
941 | |
942 void zdebugger_print(z80_context * context, char format_char, char * param) | |
943 { | |
944 uint32_t value; | |
945 char format[8]; | |
946 strcpy(format, "%s: %d\n"); | |
947 switch (format_char) | |
948 { | |
949 case 'x': | |
950 case 'X': | |
951 case 'd': | |
952 case 'c': | |
953 format[5] = format_char; | |
954 break; | |
955 case '\0': | |
956 break; | |
957 default: | |
958 fprintf(stderr, "Unrecognized format character: %c\n", format_char); | |
959 } | |
960 switch (param[0]) | |
961 { | |
962 case 'a': | |
963 if (param[1] == 'f') { | |
964 if(param[2] == '\'') { | |
965 value = context->alt_regs[Z80_A] << 8; | |
966 value |= context->alt_flags[ZF_S] << 7; | |
967 value |= context->alt_flags[ZF_Z] << 6; | |
968 value |= context->alt_flags[ZF_H] << 4; | |
969 value |= context->alt_flags[ZF_PV] << 2; | |
970 value |= context->alt_flags[ZF_N] << 1; | |
971 value |= context->alt_flags[ZF_C]; | |
972 } else { | |
973 value = context->regs[Z80_A] << 8; | |
974 value |= context->flags[ZF_S] << 7; | |
975 value |= context->flags[ZF_Z] << 6; | |
976 value |= context->flags[ZF_H] << 4; | |
977 value |= context->flags[ZF_PV] << 2; | |
978 value |= context->flags[ZF_N] << 1; | |
979 value |= context->flags[ZF_C]; | |
980 } | |
981 } else if(param[1] == '\'') { | |
982 value = context->alt_regs[Z80_A]; | |
983 } else { | |
984 value = context->regs[Z80_A]; | |
985 } | |
986 break; | |
987 case 'b': | |
988 if (param[1] == 'c') { | |
989 if(param[2] == '\'') { | |
990 value = context->alt_regs[Z80_B] << 8; | |
991 value |= context->alt_regs[Z80_C]; | |
992 } else { | |
993 value = context->regs[Z80_B] << 8; | |
994 value |= context->regs[Z80_C]; | |
995 } | |
996 } else if(param[1] == '\'') { | |
997 value = context->alt_regs[Z80_B]; | |
998 } else if(param[1] == 'a') { | |
999 value = context->bank_reg << 15; | |
1000 } else { | |
1001 value = context->regs[Z80_B]; | |
1002 } | |
1003 break; | |
1004 case 'c': | |
1005 if(param[1] == '\'') { | |
1006 value = context->alt_regs[Z80_C]; | |
1007 } else if(param[1] == 'y') { | |
1008 value = context->current_cycle; | |
1009 } else { | |
1010 value = context->regs[Z80_C]; | |
1011 } | |
1012 break; | |
1013 case 'd': | |
1014 if (param[1] == 'e') { | |
1015 if(param[2] == '\'') { | |
1016 value = context->alt_regs[Z80_D] << 8; | |
1017 value |= context->alt_regs[Z80_E]; | |
1018 } else { | |
1019 value = context->regs[Z80_D] << 8; | |
1020 value |= context->regs[Z80_E]; | |
1021 } | |
1022 } else if(param[1] == '\'') { | |
1023 value = context->alt_regs[Z80_D]; | |
1024 } else { | |
1025 value = context->regs[Z80_D]; | |
1026 } | |
1027 break; | |
1028 case 'e': | |
1029 if(param[1] == '\'') { | |
1030 value = context->alt_regs[Z80_E]; | |
1031 } else { | |
1032 value = context->regs[Z80_E]; | |
1033 } | |
1034 break; | |
1035 case 'f': | |
1036 if(param[2] == '\'') { | |
1037 value = context->alt_flags[ZF_S] << 7; | |
1038 value |= context->alt_flags[ZF_Z] << 6; | |
1039 value |= context->alt_flags[ZF_H] << 4; | |
1040 value |= context->alt_flags[ZF_PV] << 2; | |
1041 value |= context->alt_flags[ZF_N] << 1; | |
1042 value |= context->alt_flags[ZF_C]; | |
1043 } else { | |
1044 value = context->flags[ZF_S] << 7; | |
1045 value |= context->flags[ZF_Z] << 6; | |
1046 value |= context->flags[ZF_H] << 4; | |
1047 value |= context->flags[ZF_PV] << 2; | |
1048 value |= context->flags[ZF_N] << 1; | |
1049 value |= context->flags[ZF_C]; | |
1050 } | |
1051 break; | |
1052 case 'h': | |
1053 if (param[1] == 'l') { | |
1054 if(param[2] == '\'') { | |
1055 value = context->alt_regs[Z80_H] << 8; | |
1056 value |= context->alt_regs[Z80_L]; | |
1057 } else { | |
1058 value = context->regs[Z80_H] << 8; | |
1059 value |= context->regs[Z80_L]; | |
1060 } | |
1061 } else if(param[1] == '\'') { | |
1062 value = context->alt_regs[Z80_H]; | |
1063 } else { | |
1064 value = context->regs[Z80_H]; | |
1065 } | |
1066 break; | |
1067 case 'l': | |
1068 if(param[1] == '\'') { | |
1069 value = context->alt_regs[Z80_L]; | |
1070 } else { | |
1071 value = context->regs[Z80_L]; | |
1072 } | |
1073 break; | |
1074 case 'i': | |
1075 if(param[1] == 'x') { | |
1076 if (param[2] == 'h') { | |
1077 value = context->regs[Z80_IXH]; | |
1078 } else if(param[2] == 'l') { | |
1079 value = context->regs[Z80_IXL]; | |
1080 } else { | |
1081 value = context->regs[Z80_IXH] << 8; | |
1082 value |= context->regs[Z80_IXL]; | |
1083 } | |
1084 } else if(param[1] == 'y') { | |
1085 if (param[2] == 'h') { | |
1086 value = context->regs[Z80_IYH]; | |
1087 } else if(param[2] == 'l') { | |
1088 value = context->regs[Z80_IYL]; | |
1089 } else { | |
1090 value = context->regs[Z80_IYH] << 8; | |
1091 value |= context->regs[Z80_IYL]; | |
1092 } | |
1093 } else if(param[1] == 'n') { | |
1094 value = context->int_cycle; | |
1095 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '1') { | |
1096 value = context->iff1; | |
1097 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '2') { | |
1098 value = context->iff2; | |
1099 } else { | |
1100 value = context->im; | |
1101 } | |
1102 break; | |
1103 case 's': | |
1104 if (param[1] == 'p') { | |
1105 value = context->sp; | |
1106 } | |
1107 break; | |
1108 case '0': | |
1109 if (param[1] == 'x') { | |
1110 uint16_t p_addr = strtol(param+2, NULL, 16); | |
1111 if (p_addr < 0x4000) { | |
1112 value = z80_ram[p_addr & 0x1FFF]; | |
1113 } else if(p_addr >= 0x8000) { | |
1114 uint32_t v_addr = context->bank_reg << 15; | |
1115 v_addr += p_addr & 0x7FFF; | |
1116 if (v_addr < 0x400000) { | |
1117 value = cart[v_addr/2]; | |
1118 } else if(v_addr > 0xE00000) { | |
1119 value = ram[(v_addr & 0xFFFF)/2]; | |
1120 } | |
1121 if (v_addr & 1) { | |
1122 value &= 0xFF; | |
1123 } else { | |
1124 value >>= 8; | |
1125 } | |
1126 } | |
1127 } | |
1128 break; | |
1129 } | |
1130 printf(format, param, value); | |
1131 } | |
1132 | |
1133 z80_context * zdebugger(z80_context * context, uint16_t address) | |
1134 { | |
1135 static char last_cmd[1024]; | |
1136 char input_buf[1024]; | |
1137 static uint16_t branch_t; | |
1138 static uint16_t branch_f; | |
1139 z80inst inst; | |
1140 //Check if this is a user set breakpoint, or just a temporary one | |
1141 bp_def ** this_bp = find_breakpoint(&zbreakpoints, address); | |
1142 if (*this_bp) { | |
1143 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); | |
1144 } else { | |
1145 zremove_breakpoint(context, address); | |
1146 } | |
1147 uint8_t * pc; | |
1148 if (address < 0x4000) { | |
1149 pc = z80_ram + (address & 0x1FFF); | |
1150 } else if (address >= 0x8000) { | |
1151 if (context->bank_reg < (0x400000 >> 15)) { | |
1152 fprintf(stderr, "Entered Z80 debugger in banked memory address %X, which is not yet supported\n", address); | |
1153 exit(1); | |
1154 } else { | |
1155 fprintf(stderr, "Entered Z80 debugger in banked memory address %X, but the bank is not pointed to a cartridge address\n", address); | |
1156 exit(1); | |
1157 } | |
1158 } else { | |
1159 fprintf(stderr, "Entered Z80 debugger at address %X\n", address); | |
1160 exit(1); | |
1161 } | |
1162 for (disp_def * cur = zdisplays; cur; cur = cur->next) { | |
1163 zdebugger_print(context, cur->format_char, cur->param); | |
1164 } | |
1165 uint8_t * after_pc = z80_decode(pc, &inst); | |
1166 z80_disasm(&inst, input_buf, address); | |
1167 printf("%X:\t%s\n", address, input_buf); | |
1168 uint16_t after = address + (after_pc-pc); | |
1169 int debugging = 1; | |
1170 while(debugging) { | |
1171 fputs(">", stdout); | |
1172 if (!fgets(input_buf, sizeof(input_buf), stdin)) { | |
1173 fputs("fgets failed", stderr); | |
1174 break; | |
1175 } | |
1176 strip_nl(input_buf); | |
1177 //hitting enter repeats last command | |
1178 if (input_buf[0]) { | |
1179 strcpy(last_cmd, input_buf); | |
1180 } else { | |
1181 strcpy(input_buf, last_cmd); | |
1182 } | |
1183 char * param; | |
1184 char format[8]; | |
1185 uint32_t value; | |
1186 bp_def * new_bp; | |
1187 switch(input_buf[0]) | |
1188 { | |
1189 case 'a': | |
1190 param = find_param(input_buf); | |
1191 if (!param) { | |
1192 fputs("a command requires a parameter\n", stderr); | |
1193 break; | |
1194 } | |
1195 value = strtol(param, NULL, 16); | |
1196 zinsert_breakpoint(context, value, (uint8_t *)zdebugger); | |
1197 debugging = 0; | |
1198 break; | |
1199 case 'b': | |
1200 param = find_param(input_buf); | |
1201 if (!param) { | |
1202 fputs("b command requires a parameter\n", stderr); | |
1203 break; | |
1204 } | |
1205 value = strtol(param, NULL, 16); | |
1206 zinsert_breakpoint(context, value, (uint8_t *)zdebugger); | |
1207 new_bp = malloc(sizeof(bp_def)); | |
1208 new_bp->next = zbreakpoints; | |
1209 new_bp->address = value; | |
1210 new_bp->index = zbp_index++; | |
1211 zbreakpoints = new_bp; | |
1212 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value); | |
1213 break; | |
1214 case 'c': | |
1215 puts("Continuing"); | |
1216 debugging = 0; | |
1217 break; | |
1218 case 'd': | |
1219 if (input_buf[1] == 'i') { | |
1220 char format_char = 0; | |
1221 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) { | |
1222 if (input_buf[i] == '/') { | |
1223 format_char = input_buf[i+1]; | |
1224 break; | |
1225 } | |
1226 } | |
1227 param = find_param(input_buf); | |
1228 if (!param) { | |
1229 fputs("display command requires a parameter\n", stderr); | |
1230 break; | |
1231 } | |
1232 zdebugger_print(context, format_char, param); | |
1233 add_display(&zdisplays, &zdisp_index, format_char, param); | |
1234 } else if (input_buf[1] == 'e' || input_buf[1] == ' ') { | |
1235 param = find_param(input_buf); | |
1236 if (!param) { | |
1237 fputs("delete command requires a parameter\n", stderr); | |
1238 break; | |
1239 } | |
1240 if (param[0] >= '0' && param[0] <= '9') { | |
1241 value = atoi(param); | |
1242 this_bp = find_breakpoint_idx(&zbreakpoints, value); | |
1243 if (!*this_bp) { | |
1244 fprintf(stderr, "Breakpoint %d does not exist\n", value); | |
1245 break; | |
1246 } | |
1247 new_bp = *this_bp; | |
1248 zremove_breakpoint(context, new_bp->address); | |
1249 *this_bp = new_bp->next; | |
1250 free(new_bp); | |
1251 } else if (param[0] == 'd') { | |
1252 param = find_param(param); | |
1253 if (!param) { | |
1254 fputs("delete display command requires a parameter\n", stderr); | |
1255 break; | |
1256 } | |
1257 remove_display(&zdisplays, atoi(param)); | |
1258 } | |
1259 } | |
1260 break; | |
1261 case 'n': | |
1262 //TODO: Handle conditional branch instructions | |
1263 if (inst.op == Z80_JP) { | |
1264 if (inst.addr_mode == Z80_IMMED) { | |
1265 after = inst.immed; | |
1266 } else if (inst.ea_reg == Z80_HL) { | |
1267 after = context->regs[Z80_H] << 8 | context->regs[Z80_L]; | |
1268 } else if (inst.ea_reg == Z80_IX) { | |
1269 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL]; | |
1270 } else if (inst.ea_reg == Z80_IY) { | |
1271 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL]; | |
1272 } | |
1273 } else if(inst.op == Z80_JR) { | |
1274 after += inst.immed; | |
1275 } else if(inst.op == Z80_RET) { | |
1276 if (context->sp < 0x4000) { | |
1277 after = z80_ram[context->sp & 0x1FFF] | z80_ram[(context->sp+1) & 0x1FFF] << 8; | |
1278 } | |
1279 } | |
1280 zinsert_breakpoint(context, after, (uint8_t *)zdebugger); | |
1281 debugging = 0; | |
1282 break; | |
1283 case 'p': | |
1284 param = find_param(input_buf); | |
1285 if (!param) { | |
1286 fputs("p command requires a parameter\n", stderr); | |
1287 break; | |
1288 } | |
1289 zdebugger_print(context, input_buf[1] == '/' ? input_buf[2] : 0, param); | |
1290 break; | |
1291 case 'q': | |
1292 puts("Quitting"); | |
1293 exit(0); | |
1294 break; | |
1295 case 's': { | |
1296 param = find_param(input_buf); | |
1297 if (!param) { | |
1298 fputs("s command requires a file name\n", stderr); | |
1299 break; | |
1300 } | |
1301 FILE * f = fopen(param, "wb"); | |
1302 if (f) { | |
1303 if(fwrite(z80_ram, 1, sizeof(z80_ram), f) != sizeof(z80_ram)) { | |
1304 fputs("Error writing file\n", stderr); | |
1305 } | |
1306 fclose(f); | |
1307 } else { | |
1308 fprintf(stderr, "Could not open %s for writing\n", param); | |
1309 } | |
1310 break; | |
1311 } | |
1312 default: | |
1313 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); | |
1314 break; | |
1315 } | |
1316 } | |
1317 return context; | |
1318 } | |
1319 | |
1320 m68k_context * debugger(m68k_context * context, uint32_t address) | |
1321 { | |
1322 static char last_cmd[1024]; | |
1323 char input_buf[1024]; | |
1324 static uint32_t branch_t; | |
1325 static uint32_t branch_f; | |
1326 m68kinst inst; | |
1327 //probably not necessary, but let's play it safe | |
1328 address &= 0xFFFFFF; | |
1329 if (address == branch_t) { | |
1330 bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f); | |
1331 if (!*f_bp) { | |
1332 remove_breakpoint(context, branch_f); | |
1333 } | |
1334 branch_t = branch_f = 0; | |
1335 } else if(address == branch_f) { | |
1336 bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t); | |
1337 if (!*t_bp) { | |
1338 remove_breakpoint(context, branch_t); | |
1339 } | |
1340 branch_t = branch_f = 0; | |
1341 } | |
1342 //Check if this is a user set breakpoint, or just a temporary one | |
1343 bp_def ** this_bp = find_breakpoint(&breakpoints, address); | |
1344 if (*this_bp) { | |
1345 printf("68K Breakpoint %d hit\n", (*this_bp)->index); | |
1346 } else { | |
1347 remove_breakpoint(context, address); | |
1348 } | |
1349 uint16_t * pc; | |
1350 if (address < 0x400000) { | |
1351 pc = cart + address/2; | |
1352 } else if(address > 0xE00000) { | |
1353 pc = ram + (address & 0xFFFF)/2; | |
1354 } else { | |
1355 fprintf(stderr, "Entered 68K debugger at address %X\n", address); | |
1356 exit(1); | |
1357 } | |
1358 uint16_t * after_pc = m68k_decode(pc, &inst, address); | |
1359 m68k_disasm(&inst, input_buf); | |
1360 printf("%X: %s\n", address, input_buf); | |
1361 uint32_t after = address + (after_pc-pc)*2; | |
1362 int debugging = 1; | |
1363 while (debugging) { | |
1364 fputs(">", stdout); | |
1365 if (!fgets(input_buf, sizeof(input_buf), stdin)) { | |
1366 fputs("fgets failed", stderr); | |
1367 break; | |
1368 } | |
1369 strip_nl(input_buf); | |
1370 //hitting enter repeats last command | |
1371 if (input_buf[0]) { | |
1372 strcpy(last_cmd, input_buf); | |
1373 } else { | |
1374 strcpy(input_buf, last_cmd); | |
1375 } | |
1376 char * param; | |
1377 char format[8]; | |
1378 uint32_t value; | |
1379 bp_def * new_bp; | |
1380 switch(input_buf[0]) | |
1381 { | |
1382 case 'c': | |
1383 puts("Continuing"); | |
1384 debugging = 0; | |
1385 break; | |
1386 case 'b': | |
1387 param = find_param(input_buf); | |
1388 if (!param) { | |
1389 fputs("b command requires a parameter\n", stderr); | |
1390 break; | |
1391 } | |
1392 value = strtol(param, NULL, 16); | |
1393 insert_breakpoint(context, value, (uint8_t *)debugger); | |
1394 new_bp = malloc(sizeof(bp_def)); | |
1395 new_bp->next = breakpoints; | |
1396 new_bp->address = value; | |
1397 new_bp->index = bp_index++; | |
1398 breakpoints = new_bp; | |
1399 printf("68K Breakpoint %d set at %X\n", new_bp->index, value); | |
1400 break; | |
1401 case 'a': | |
1402 param = find_param(input_buf); | |
1403 if (!param) { | |
1404 fputs("a command requires a parameter\n", stderr); | |
1405 break; | |
1406 } | |
1407 value = strtol(param, NULL, 16); | |
1408 insert_breakpoint(context, value, (uint8_t *)debugger); | |
1409 debugging = 0; | |
1410 break; | |
1411 case 'd': | |
1412 param = find_param(input_buf); | |
1413 if (!param) { | |
1414 fputs("d command requires a parameter\n", stderr); | |
1415 break; | |
1416 } | |
1417 value = atoi(param); | |
1418 this_bp = find_breakpoint_idx(&breakpoints, value); | |
1419 if (!*this_bp) { | |
1420 fprintf(stderr, "Breakpoint %d does not exist\n", value); | |
1421 break; | |
1422 } | |
1423 new_bp = *this_bp; | |
1424 *this_bp = (*this_bp)->next; | |
1425 free(new_bp); | |
1426 break; | |
1427 case 'p': | |
1428 strcpy(format, "%s: %d\n"); | |
1429 if (input_buf[1] == '/') { | |
1430 switch (input_buf[2]) | |
1431 { | |
1432 case 'x': | |
1433 case 'X': | |
1434 case 'd': | |
1435 case 'c': | |
1436 format[5] = input_buf[2]; | |
1437 break; | |
1438 default: | |
1439 fprintf(stderr, "Unrecognized format character: %c\n", input_buf[2]); | |
1440 } | |
1441 } | |
1442 param = find_param(input_buf); | |
1443 if (!param) { | |
1444 fputs("p command requires a parameter\n", stderr); | |
1445 break; | |
1446 } | |
1447 if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') { | |
1448 value = context->dregs[param[1]-'0']; | |
1449 } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') { | |
1450 value = context->aregs[param[1]-'0']; | |
1451 } else if (param[0] == 'S' && param[1] == 'R') { | |
1452 value = (context->status << 8); | |
1453 for (int flag = 0; flag < 5; flag++) { | |
1454 value |= context->flags[flag] << (4-flag); | |
1455 } | |
1456 } else if(param[0] == 'c') { | |
1457 value = context->current_cycle; | |
1458 } else if (param[0] == '0' && param[1] == 'x') { | |
1459 uint32_t p_addr = strtol(param+2, NULL, 16); | |
1460 value = read_dma_value(p_addr/2); | |
1461 } else { | |
1462 fprintf(stderr, "Unrecognized parameter to p: %s\n", param); | |
1463 break; | |
1464 } | |
1465 printf(format, param, value); | |
1466 break; | |
1467 case 'n': | |
1468 if (inst.op == M68K_RTS) { | |
1469 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
1470 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
1471 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
1472 } else if(m68k_is_noncall_branch(&inst)) { | |
1473 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
1474 branch_f = after; | |
1475 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1476 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
1477 } else if(inst.op == M68K_DBCC) { | |
1478 if ( inst.extra.cond == COND_FALSE) { | |
1479 if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { | |
1480 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1481 } | |
1482 } else { | |
1483 branch_t = after; | |
1484 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1485 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
1486 } | |
1487 } else { | |
1488 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1489 } | |
1490 } | |
1491 insert_breakpoint(context, after, (uint8_t *)debugger); | |
1492 debugging = 0; | |
1493 break; | |
1494 case 'o': | |
1495 if (inst.op == M68K_RTS) { | |
1496 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
1497 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
1498 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
1499 } else if(m68k_is_noncall_branch(&inst)) { | |
1500 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
1501 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1502 if (branch_t < after) { | |
1503 branch_t = 0; | |
1504 } else { | |
1505 branch_f = after; | |
1506 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
1507 } | |
1508 } else if(inst.op == M68K_DBCC) { | |
1509 uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1510 if (target > after) { | |
1511 if (inst.extra.cond == COND_FALSE) { | |
1512 after = target; | |
1513 } else { | |
1514 branch_f = target; | |
1515 branch_t = after; | |
1516 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
1517 } | |
1518 } | |
1519 } else { | |
1520 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1521 } | |
1522 } | |
1523 insert_breakpoint(context, after, (uint8_t *)debugger); | |
1524 debugging = 0; | |
1525 break; | |
1526 case 's': | |
1527 if (inst.op == M68K_RTS) { | |
1528 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
1529 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
1530 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
1531 } else if(m68k_is_branch(&inst)) { | |
1532 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
1533 branch_f = after; | |
1534 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1535 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
1536 } else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) { | |
1537 branch_t = after; | |
1538 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1539 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
1540 } else { | |
1541 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
1542 } | |
1543 } | |
1544 insert_breakpoint(context, after, (uint8_t *)debugger); | |
1545 debugging = 0; | |
1546 break; | |
1547 case 'v': { | |
1548 genesis_context * gen = context->system; | |
1549 //VDP debug commands | |
1550 switch(input_buf[1]) | |
1551 { | |
1552 case 's': | |
1553 vdp_print_sprite_table(gen->vdp); | |
1554 break; | |
1555 case 'r': | |
1556 vdp_print_reg_explain(gen->vdp); | |
1557 break; | |
1558 } | |
1559 break; | |
1560 } | |
1561 case 'z': { | |
1562 genesis_context * gen = context->system; | |
1563 //Z80 debug commands | |
1564 switch(input_buf[1]) | |
1565 { | |
1566 case 'b': | |
1567 param = find_param(input_buf); | |
1568 if (!param) { | |
1569 fputs("zb command requires a parameter\n", stderr); | |
1570 break; | |
1571 } | |
1572 value = strtol(param, NULL, 16); | |
1573 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger); | |
1574 new_bp = malloc(sizeof(bp_def)); | |
1575 new_bp->next = zbreakpoints; | |
1576 new_bp->address = value; | |
1577 new_bp->index = zbp_index++; | |
1578 zbreakpoints = new_bp; | |
1579 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value); | |
1580 break; | |
1581 case 'p': | |
1582 param = find_param(input_buf); | |
1583 if (!param) { | |
1584 fputs("zp command requires a parameter\n", stderr); | |
1585 break; | |
1586 } | |
1587 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); | |
1588 } | |
1589 break; | |
1590 } | |
1591 case 'q': | |
1592 puts("Quitting"); | |
1593 exit(0); | |
1594 break; | |
1595 default: | |
1596 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); | |
1597 break; | |
1598 } | |
1599 } | |
1600 return context; | |
1601 } | |
1602 | |
1603 void set_speed_percent(genesis_context * context, uint32_t percent) | 851 void set_speed_percent(genesis_context * context, uint32_t percent) |
1604 { | 852 { |
1605 uint32_t old_clock = context->master_clock; | 853 uint32_t old_clock = context->master_clock; |
1606 context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100; | 854 context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100; |
1607 while (context->ym->current_cycle != context->psg->cycles) { | 855 while (context->ym->current_cycle != context->psg->cycles) { |