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) {