trunk/src/emu/debug/dvbpoints.c
| r23645 | r23646 | |
| 2 | 2 | |
| 3 | 3 | dvpoints.c |
| 4 | 4 | |
| 5 | | Breakpoint debugger view. |
| 5 | Breakpoint debugger view. |
| 6 | 6 | |
| 7 | 7 | **************************************************************************** |
| 8 | 8 | |
| r23645 | r23646 | |
| 38 | 38 | ***************************************************************************/ |
| 39 | 39 | |
| 40 | 40 | #include "emu.h" |
| 41 | | #include "debugvw.h" |
| 42 | 41 | #include "dvbpoints.h" |
| 43 | | #include "debugcpu.h" |
| 44 | 42 | |
| 45 | 43 | |
| 46 | 44 | |
| r23645 | r23646 | |
| 53 | 51 | //------------------------------------------------- |
| 54 | 52 | |
| 55 | 53 | debug_view_breakpoints::debug_view_breakpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate) |
| 56 | | : debug_view(machine, DVT_BREAK_POINTS, osdupdate, osdprivate) |
| 54 | : debug_view(machine, DVT_BREAK_POINTS, osdupdate, osdprivate), |
| 55 | m_sortType(SORT_INDEX_ASCENDING) |
| 57 | 56 | { |
| 58 | 57 | // fail if no available sources |
| 59 | 58 | enumerate_sources(); |
| r23645 | r23646 | |
| 61 | 60 | throw std::bad_alloc(); |
| 62 | 61 | |
| 63 | 62 | // configure the view |
| 64 | | m_total.y = 50; // TODO |
| 65 | | m_supports_cursor = true; |
| 63 | m_total.y = 10; |
| 64 | m_supports_cursor = false; |
| 66 | 65 | } |
| 67 | 66 | |
| 68 | 67 | |
| r23645 | r23646 | |
| 126 | 125 | |
| 127 | 126 | void debug_view_breakpoints::view_click(const int button, const debug_view_xy& pos) |
| 128 | 127 | { |
| 128 | bool clickedTopRow = (m_topleft.y == pos.y); |
| 129 | |
| 130 | if (clickedTopRow) |
| 131 | { |
| 132 | if (pos.x < 5 && m_sortType == SORT_INDEX_ASCENDING) |
| 133 | m_sortType = SORT_INDEX_DESCENDING; |
| 134 | else if (pos.x < 5) |
| 135 | m_sortType = SORT_INDEX_ASCENDING; |
| 136 | else if (pos.x < 9 && m_sortType == SORT_ENABLED_ASCENDING) |
| 137 | m_sortType = SORT_ENABLED_DESCENDING; |
| 138 | else if (pos.x < 9) |
| 139 | m_sortType = SORT_ENABLED_ASCENDING; |
| 140 | else if (pos.x < 31 && m_sortType == SORT_CPU_ASCENDING) |
| 141 | m_sortType = SORT_CPU_DESCENDING; |
| 142 | else if (pos.x < 31) |
| 143 | m_sortType = SORT_CPU_ASCENDING; |
| 144 | else if (pos.x < 45 && m_sortType == SORT_ADDRESS_ASCENDING) |
| 145 | m_sortType = SORT_ADDRESS_DESCENDING; |
| 146 | else if (pos.x < 45) |
| 147 | m_sortType = SORT_ADDRESS_ASCENDING; |
| 148 | else if (pos.x < 63 && m_sortType == SORT_CONDITION_ASCENDING) |
| 149 | m_sortType = SORT_CONDITION_DESCENDING; |
| 150 | else if (pos.x < 63) |
| 151 | m_sortType = SORT_CONDITION_ASCENDING; |
| 152 | else if (pos.x < 80 && m_sortType == SORT_ACTION_ASCENDING) |
| 153 | m_sortType = SORT_ACTION_DESCENDING; |
| 154 | else if (pos.x < 80) |
| 155 | m_sortType = SORT_ACTION_ASCENDING; |
| 156 | } |
| 157 | else |
| 158 | { |
| 159 | // Gather a sorted list of all the breakpoints for all the CPUs |
| 160 | device_debug::breakpoint** bpList = NULL; |
| 161 | const int numBPs = breakpoints(SORT_NONE, bpList); |
| 162 | |
| 163 | const int bpIndex = pos.y-1; |
| 164 | if (bpIndex > numBPs || bpIndex < 0) |
| 165 | return; |
| 166 | |
| 167 | // Enable / disable |
| 168 | if (bpList[bpIndex]->enabled()) |
| 169 | bpList[bpIndex]->setEnabled(false); |
| 170 | else |
| 171 | bpList[bpIndex]->setEnabled(true); |
| 172 | |
| 173 | delete[] bpList; |
| 174 | } |
| 175 | |
| 176 | view_update(); |
| 129 | 177 | } |
| 130 | 178 | |
| 131 | 179 | |
| r23645 | r23646 | |
| 142 | 190 | } |
| 143 | 191 | } |
| 144 | 192 | |
| 145 | | //------------------------------------------------- |
| 146 | | // view_update - update the contents of the |
| 147 | | // disassembly view |
| 148 | | //------------------------------------------------- |
| 149 | 193 | |
| 150 | | void debug_view_breakpoints::view_update() |
| 194 | // Sorting functors for the qsort function |
| 195 | int cIndexAscending(const void* a, const void* b) |
| 151 | 196 | { |
| 152 | | const debug_view_source& source = *m_source; |
| 153 | | const device_debug& debugInterface = *source.device()->debug(); |
| 154 | | debug_view_char *dest = m_viewdata; |
| 197 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 198 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 199 | return left->index() > right->index(); |
| 200 | } |
| 155 | 201 | |
| 156 | | // Gather a list of all the breakpoints in reverse order |
| 202 | int cIndexDescending(const void* a, const void* b) |
| 203 | { |
| 204 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 205 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 206 | return left->index() < right->index(); |
| 207 | } |
| 208 | |
| 209 | int cEnabledAscending(const void* a, const void* b) |
| 210 | { |
| 211 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 212 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 213 | return left->enabled() < right->enabled(); |
| 214 | } |
| 215 | |
| 216 | int cEnabledDescending(const void* a, const void* b) |
| 217 | { |
| 218 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 219 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 220 | return left->enabled() > right->enabled(); |
| 221 | } |
| 222 | |
| 223 | int cCpuAscending(const void* a, const void* b) |
| 224 | { |
| 225 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 226 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 227 | const int result = strcmp(left->debugInterface()->device().tag(), right->debugInterface()->device().tag()); |
| 228 | return result >= 0; |
| 229 | } |
| 230 | |
| 231 | int cCpuDescending(const void* a, const void* b) |
| 232 | { |
| 233 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 234 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 235 | const int result = strcmp(left->debugInterface()->device().tag(), right->debugInterface()->device().tag()); |
| 236 | return result < 0; |
| 237 | } |
| 238 | |
| 239 | int cAddressAscending(const void* a, const void* b) |
| 240 | { |
| 241 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 242 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 243 | return left->address() > right->address(); |
| 244 | } |
| 245 | |
| 246 | int cAddressDescending(const void* a, const void* b) |
| 247 | { |
| 248 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 249 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 250 | return left->address() < right->address(); |
| 251 | } |
| 252 | |
| 253 | int cConditionAscending(const void* a, const void* b) |
| 254 | { |
| 255 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 256 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 257 | const int result = strcmp(left->condition(), right->condition()); |
| 258 | return result >= 0; |
| 259 | } |
| 260 | |
| 261 | int cConditionDescending(const void* a, const void* b) |
| 262 | { |
| 263 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 264 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 265 | const int result = strcmp(left->condition(), right->condition()); |
| 266 | return result < 0; |
| 267 | } |
| 268 | |
| 269 | int cActionAscending(const void* a, const void* b) |
| 270 | { |
| 271 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 272 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 273 | const int result = strcmp(left->action(), right->action()); |
| 274 | return result >= 0; |
| 275 | } |
| 276 | |
| 277 | int cActionDescending(const void* a, const void* b) |
| 278 | { |
| 279 | const device_debug::breakpoint* left = *(device_debug::breakpoint**)a; |
| 280 | const device_debug::breakpoint* right = *(device_debug::breakpoint**)b; |
| 281 | const int result = strcmp(left->action(), right->action()); |
| 282 | return result < 0; |
| 283 | } |
| 284 | |
| 285 | |
| 286 | int debug_view_breakpoints::breakpoints(SortMode sort, device_debug::breakpoint**& bpList) |
| 287 | { |
| 157 | 288 | int numBPs = 0; |
| 158 | | device_debug::breakpoint** bpList = NULL; |
| 159 | | if (debugInterface.breakpoint_first() != NULL) |
| 289 | bpList = NULL; |
| 290 | for (const debug_view_source *source = m_source_list.head(); source != NULL; source = source->next()) |
| 160 | 291 | { |
| 161 | 292 | // Alloc |
| 293 | const device_debug& debugInterface = *source->device()->debug(); |
| 162 | 294 | for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next()) |
| 163 | 295 | numBPs++; |
| 164 | 296 | bpList = new device_debug::breakpoint*[numBPs]; |
| 165 | | |
| 166 | | // Collect |
| 167 | | int i = 1; |
| 168 | | for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next()) |
| 297 | } |
| 298 | |
| 299 | int bpAddIndex = 1; |
| 300 | for (const debug_view_source *source = m_source_list.head(); source != NULL; source = source->next()) |
| 301 | { |
| 302 | device_debug& debugInterface = *source->device()->debug(); |
| 303 | if (debugInterface.breakpoint_first() != NULL) |
| 169 | 304 | { |
| 170 | | bpList[numBPs-i] = bp; |
| 171 | | i++; |
| 305 | // Collect |
| 306 | for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next()) |
| 307 | { |
| 308 | bpList[numBPs-bpAddIndex] = bp; |
| 309 | bpAddIndex++; |
| 310 | } |
| 172 | 311 | } |
| 173 | 312 | } |
| 313 | |
| 314 | // And now for the sort |
| 315 | switch (m_sortType) |
| 316 | { |
| 317 | case SORT_NONE: |
| 318 | break; |
| 319 | case SORT_INDEX_ASCENDING: |
| 320 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cIndexAscending); |
| 321 | break; |
| 322 | case SORT_INDEX_DESCENDING: |
| 323 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cIndexDescending); |
| 324 | break; |
| 325 | case SORT_ENABLED_ASCENDING: |
| 326 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cEnabledAscending); |
| 327 | break; |
| 328 | case SORT_ENABLED_DESCENDING: |
| 329 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cEnabledDescending); |
| 330 | break; |
| 331 | case SORT_CPU_ASCENDING: |
| 332 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cCpuAscending); |
| 333 | break; |
| 334 | case SORT_CPU_DESCENDING: |
| 335 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cCpuDescending); |
| 336 | break; |
| 337 | case SORT_ADDRESS_ASCENDING: |
| 338 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cAddressAscending); |
| 339 | break; |
| 340 | case SORT_ADDRESS_DESCENDING: |
| 341 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cAddressDescending); |
| 342 | break; |
| 343 | case SORT_CONDITION_ASCENDING: |
| 344 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cConditionAscending); |
| 345 | break; |
| 346 | case SORT_CONDITION_DESCENDING: |
| 347 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cConditionDescending); |
| 348 | break; |
| 349 | case SORT_ACTION_ASCENDING: |
| 350 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cActionAscending); |
| 351 | break; |
| 352 | case SORT_ACTION_DESCENDING: |
| 353 | qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cActionDescending); |
| 354 | break; |
| 355 | } |
| 356 | |
| 357 | return numBPs; |
| 358 | } |
| 174 | 359 | |
| 360 | |
| 361 | //------------------------------------------------- |
| 362 | // view_update - update the contents of the |
| 363 | // disassembly view |
| 364 | //------------------------------------------------- |
| 365 | |
| 366 | void debug_view_breakpoints::view_update() |
| 367 | { |
| 368 | // Gather a list of all the breakpoints for all the CPUs |
| 369 | device_debug::breakpoint** bpList = NULL; |
| 370 | const int numBPs = breakpoints(SORT_NONE, bpList); |
| 371 | |
| 372 | // Set the view region so the scroll bars update |
| 373 | m_total.y = numBPs+1; |
| 374 | |
| 175 | 375 | // Draw |
| 376 | debug_view_char *dest = m_viewdata; |
| 176 | 377 | for (int row = 0; row < m_visible.y; row++) |
| 177 | 378 | { |
| 178 | 379 | UINT32 effrow = m_topleft.y + row; |
| 179 | | |
| 380 | |
| 180 | 381 | // Header |
| 181 | | if (effrow == 0) |
| 382 | if (row == 0) |
| 182 | 383 | { |
| 183 | | astring header = "ID En Address Condition Action"; |
| 384 | astring header; |
| 385 | header.printf("ID"); |
| 386 | if (m_sortType == SORT_INDEX_ASCENDING) header.catprintf("\\"); |
| 387 | else if (m_sortType == SORT_INDEX_DESCENDING) header.catprintf("/"); |
| 388 | pad_astring_to_length(header, 5); |
| 389 | header.catprintf("En"); |
| 390 | if (m_sortType == SORT_ENABLED_ASCENDING) header.catprintf("\\"); |
| 391 | else if (m_sortType == SORT_ENABLED_DESCENDING) header.catprintf("/"); |
| 392 | pad_astring_to_length(header, 9); |
| 393 | header.catprintf("CPU"); |
| 394 | if (m_sortType == SORT_CPU_ASCENDING) header.catprintf("\\"); |
| 395 | else if (m_sortType == SORT_CPU_DESCENDING) header.catprintf("/"); |
| 396 | pad_astring_to_length(header, 31); |
| 397 | header.catprintf("Address"); |
| 398 | if (m_sortType == SORT_ADDRESS_ASCENDING) header.catprintf("\\"); |
| 399 | else if (m_sortType == SORT_ADDRESS_DESCENDING) header.catprintf("/"); |
| 400 | pad_astring_to_length(header, 45); |
| 401 | header.catprintf("Condition"); |
| 402 | if (m_sortType == SORT_CONDITION_ASCENDING) header.catprintf("\\"); |
| 403 | else if (m_sortType == SORT_CONDITION_DESCENDING) header.catprintf("/"); |
| 404 | pad_astring_to_length(header, 63); |
| 405 | header.catprintf("Action"); |
| 406 | if (m_sortType == SORT_ACTION_ASCENDING) header.catprintf("\\"); |
| 407 | else if (m_sortType == SORT_ACTION_DESCENDING) header.catprintf("/"); |
| 408 | pad_astring_to_length(header, 80); |
| 409 | |
| 184 | 410 | for (int i = 0; i < m_visible.x; i++) |
| 185 | 411 | { |
| 186 | 412 | dest->byte = (i < header.len()) ? header[i] : ' '; |
| r23645 | r23646 | |
| 195 | 421 | if (bpi < numBPs && bpi >= 0) |
| 196 | 422 | { |
| 197 | 423 | device_debug::breakpoint* bp = bpList[bpi]; |
| 198 | | |
| 199 | | astring buffer; |
| 424 | |
| 425 | astring buffer; |
| 200 | 426 | buffer.printf("%x", bp->index()); |
| 201 | 427 | pad_astring_to_length(buffer, 5); |
| 202 | 428 | buffer.catprintf("%c", bp->enabled() ? 'X' : 'O'); |
| 203 | 429 | pad_astring_to_length(buffer, 9); |
| 204 | | buffer.catprintf("%s", core_i64_hex_format(bp->address(), debugInterface.logaddrchars())); |
| 205 | | pad_astring_to_length(buffer, 26); |
| 430 | buffer.catprintf("%s", bp->debugInterface()->device().tag()); |
| 431 | pad_astring_to_length(buffer, 31); |
| 432 | buffer.catprintf("%s", core_i64_hex_format(bp->address(), bp->debugInterface()->logaddrchars())); |
| 433 | pad_astring_to_length(buffer, 45); |
| 206 | 434 | if (astring(bp->condition()) != astring("1")) |
| 207 | 435 | { |
| 208 | 436 | buffer.catprintf("%s", bp->condition()); |
| 209 | | pad_astring_to_length(buffer, 44); |
| 437 | pad_astring_to_length(buffer, 63); |
| 210 | 438 | } |
| 211 | 439 | if (astring(bp->action()) != astring("")) |
| 212 | 440 | { |
| 213 | 441 | buffer.catprintf("%s", bp->action()); |
| 214 | | pad_astring_to_length(buffer, 60); |
| 442 | pad_astring_to_length(buffer, 80); |
| 215 | 443 | } |
| 216 | | |
| 444 | |
| 217 | 445 | for (int i = 0; i < m_visible.x; i++) |
| 218 | 446 | { |
| 219 | 447 | dest->byte = (i < buffer.len()) ? buffer[i] : ' '; |
| 220 | 448 | dest->attrib = DCA_NORMAL; |
| 449 | |
| 450 | // Color disabled breakpoints red |
| 451 | if (i == 5 && dest->byte == 'O') |
| 452 | dest->attrib = DCA_CHANGED; |
| 453 | |
| 221 | 454 | dest++; |
| 222 | 455 | } |
| 223 | 456 | continue; |
| 224 | 457 | } |
| 225 | | |
| 458 | |
| 226 | 459 | // Fill the remaining vertical space |
| 227 | 460 | for (int i = 0; i < m_visible.x; i++) |
| 228 | 461 | { |
| r23645 | r23646 | |
| 231 | 464 | dest++; |
| 232 | 465 | } |
| 233 | 466 | } |
| 234 | | |
| 235 | | delete bpList; |
| 467 | |
| 468 | delete[] bpList; |
| 236 | 469 | } |