fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1157 lines 21 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/lib/monitor.c * 7 * Created: 2006-12-13 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2006-2024 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <stdarg.h> 26#include <string.h> 27 28#include <lib/monitor.h> 29#include <lib/cmd.h> 30#include <lib/console.h> 31#include <lib/ihex.h> 32#include <lib/mhex.h> 33#include <lib/srec.h> 34#include <lib/thex.h> 35 36 37#define MON_FORMAT_NONE 0 38#define MON_FORMAT_BINARY 1 39#define MON_FORMAT_IHEX 2 40#define MON_FORMAT_MHEX 3 41#define MON_FORMAT_SREC 4 42#define MON_FORMAT_THEX 5 43 44 45static mon_cmd_t par_cmd[] = { 46 { "di", "name [drive] [ro] [rw]", "insert a disk" }, 47 { "d", "[addr [cnt]]", "dump memory" }, 48 { "e", "addr [val|string...]", "enter bytes into memory" }, 49 { "f", "addr cnt [val...]", "find bytes in memory" }, 50 { "h", "", "print help" }, 51 { "load", "name [fmt] [a [n]]", "read a file into memory" }, 52 { "mem", "[ro|rw]", "set memory ro or rw" }, 53 { "m", "msg [val]", "send a message to the emulator core" }, 54 { "q", "", "quit" }, 55 { "save", "name [fmt] [a n...]", "write memory to a file" }, 56 { "v", "[expr...]", "evaluate expressions" }, 57 { "y", "src dst cnt", "copy memory" } 58}; 59 60static mon_cmd_t par_cmd_bp[] = { 61 { "bc", "[index]", "clear a breakpoint or all" }, 62 { "bl", "", "list breakpoints" }, 63 { "bs", "addr [pass [reset]]", "set an address breakpoint [pass=1 reset=0]" }, 64 { "bsx", "expr [pass [reset]]", "set an expression breakpoint [pass=1 reset=0]" } 65}; 66 67 68void mon_init (monitor_t *mon) 69{ 70 mon->cmdext = NULL; 71 mon->docmd = NULL; 72 73 mon->msgext = NULL; 74 mon->setmsg = NULL; 75 76 mon->get_mem8_ext = NULL; 77 mon->get_mem8 = NULL; 78 79 mon->set_mem8_ext = NULL; 80 mon->set_mem8 = NULL; 81 82 mon->set_mem8rw_ext = NULL; 83 mon->set_mem8rw = NULL; 84 85 mon->memory_mode = 0; 86 87 mon->default_seg = 0; 88 89 mon->last_addr = 0; 90 mon->last_ofs = 0; 91 92 mon->cmd_cnt = 0; 93 mon->cmd = NULL; 94 95 mon->rw = 0; 96 mon->terminate = 0; 97 mon->prompt = NULL; 98 99 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0])); 100} 101 102void mon_free (monitor_t *mon) 103{ 104 free (mon->cmd); 105} 106 107monitor_t *mon_new (void) 108{ 109 monitor_t *mon; 110 111 mon = malloc (sizeof (monitor_t)); 112 if (mon == NULL) { 113 return (NULL); 114 } 115 116 mon_init (mon); 117 118 return (mon); 119} 120 121void mon_del (monitor_t *mon) 122{ 123 if (mon != NULL) { 124 mon_free (mon); 125 free (mon); 126 } 127} 128 129void mon_set_cmd_fct (monitor_t *mon, void *fct, void *ext) 130{ 131 mon->cmdext = ext; 132 mon->docmd = fct; 133} 134 135void mon_set_msg_fct (monitor_t *mon, void *fct, void *ext) 136{ 137 mon->msgext = ext; 138 mon->setmsg = fct; 139} 140 141void mon_set_get_mem_fct (monitor_t *mon, void *ext, void *fct) 142{ 143 mon->get_mem8_ext = ext; 144 mon->get_mem8 = fct; 145} 146 147void mon_set_set_mem_fct (monitor_t *mon, void *ext, void *fct) 148{ 149 mon->set_mem8_ext = ext; 150 mon->set_mem8 = fct; 151} 152 153void mon_set_set_memrw_fct (monitor_t *mon, void *ext, void *fct) 154{ 155 mon->set_mem8rw_ext = ext; 156 mon->set_mem8rw = fct; 157} 158 159void mon_set_memory_mode (monitor_t *mon, unsigned mode) 160{ 161 mon->memory_mode = mode; 162} 163 164void mon_set_terminate (monitor_t *mon, int val) 165{ 166 mon->terminate = (val != 0); 167} 168 169void mon_set_prompt (monitor_t *mon, const char *str) 170{ 171 mon->prompt = str; 172} 173 174static 175unsigned char mon_get_mem8 (monitor_t *mon, unsigned long addr) 176{ 177 if (mon->get_mem8 != NULL) { 178 return (mon->get_mem8 (mon->get_mem8_ext, addr)); 179 } 180 181 return (0); 182} 183 184static 185void mon_set_mem8 (monitor_t *mon, unsigned long addr, unsigned char val) 186{ 187 if (mon->rw) { 188 if (mon->set_mem8rw != NULL) { 189 mon->set_mem8rw (mon->set_mem8_ext, addr, val); 190 } 191 } 192 else { 193 if (mon->set_mem8 != NULL) { 194 mon->set_mem8 (mon->set_mem8_ext, addr, val); 195 } 196 } 197} 198 199#if 0 200static 201int mon_set_msg (monitor_t *mon, const char *msg, const char *val) 202{ 203 if (mon->setmsg != NULL) { 204 return (mon->setmsg (mon->msgext, msg, val)); 205 } 206 207 return (1); 208} 209 210static 211int mon_get_msg (monitor_t *mon, const char *msg, char *val, unsigned max) 212{ 213 if (mon->getmsg != NULL) { 214 return (mon->getmsg (mon->msgext, msg, val, max)); 215 } 216 217 return (1); 218} 219#endif 220 221static 222const char *mon_get_ext (const char *src) 223{ 224 const char *ext; 225 226 ext = src; 227 228 while (*src != 0) { 229 if (*src == '.') { 230 ext = src + 1; 231 } 232 233 src += 1; 234 } 235 236 return (ext); 237} 238 239static 240unsigned mon_guess_format (const char *fname) 241{ 242 const char *ext; 243 244 ext = mon_get_ext (fname); 245 246 if (strcasecmp (ext, "bin") == 0) { 247 return (MON_FORMAT_BINARY); 248 } 249 else if (strcasecmp (ext, "ihex") == 0) { 250 return (MON_FORMAT_IHEX); 251 } 252 else if (strcasecmp (ext, "ihx") == 0) { 253 return (MON_FORMAT_IHEX); 254 } 255 else if (strcasecmp (ext, "hex") == 0) { 256 return (MON_FORMAT_IHEX); 257 } 258 else if (strcasecmp (ext, "mhex") == 0) { 259 return (MON_FORMAT_MHEX); 260 } 261 else if (strcasecmp (ext, "srec") == 0) { 262 return (MON_FORMAT_SREC); 263 } 264 else if (strcasecmp (ext, "thex") == 0) { 265 return (MON_FORMAT_THEX); 266 } 267 268 return (MON_FORMAT_BINARY); 269} 270 271static 272int mon_match_format (monitor_t *mon, cmd_t *cmd, unsigned *fmt) 273{ 274 if (cmd_match (cmd, "bin")) { 275 *fmt = MON_FORMAT_BINARY; 276 } 277 else if (cmd_match (cmd, "ihex")) { 278 *fmt = MON_FORMAT_IHEX; 279 } 280 else if (cmd_match (cmd, "mhex")) { 281 *fmt = MON_FORMAT_MHEX; 282 } 283 else if (cmd_match (cmd, "srec")) { 284 *fmt = MON_FORMAT_SREC; 285 } 286 else if (cmd_match (cmd, "thex")) { 287 *fmt = MON_FORMAT_THEX; 288 } 289 else { 290 *fmt = MON_FORMAT_NONE; 291 return (0); 292 } 293 294 return (1); 295} 296 297static 298int mon_match_address (monitor_t *mon, cmd_t *cmd, unsigned long *addr, unsigned short *seg, unsigned short *ofs) 299{ 300 unsigned short tseg, tofs; 301 302 if (mon->memory_mode == 0) { 303 if (!cmd_match_uint32 (cmd, addr)) { 304 return (0); 305 } 306 307 tseg = *addr >> 4; 308 tofs = *addr & 0x0f; 309 } 310 else { 311 tseg = mon->default_seg; 312 313 if (!cmd_match_uint16_16 (cmd, &tseg, &tofs)) { 314 return (0); 315 } 316 317 mon->default_seg = tseg; 318 319 *addr = ((unsigned long) tseg << 4) + tofs; 320 } 321 322 if (seg != NULL) { 323 *seg = tseg; 324 } 325 326 if (ofs != NULL) { 327 *ofs = tofs; 328 } 329 330 return (1); 331} 332 333int mon_cmd_add (monitor_t *mon, const mon_cmd_t *cmd, unsigned cnt) 334{ 335 unsigned i; 336 mon_cmd_t *c; 337 338 c = realloc (mon->cmd, (mon->cmd_cnt + cnt) * sizeof (mon_cmd_t)); 339 340 if (c == NULL) { 341 return (1); 342 } 343 344 mon->cmd = c; 345 346 while (cnt > 0) { 347 i = mon->cmd_cnt; 348 349 while (i > 0) { 350 if (strcmp (cmd->cmd, c[i - 1].cmd) >= 0) { 351 break; 352 } 353 354 c[i] = c[i - 1]; 355 356 i -= 1; 357 } 358 359 c[i] = *cmd; 360 361 mon->cmd_cnt += 1; 362 363 cmd += 1; 364 cnt -= 1; 365 } 366 367 return (0); 368} 369 370int mon_cmd_add_bp (monitor_t *mon) 371{ 372 return (mon_cmd_add (mon, par_cmd_bp, sizeof (par_cmd_bp) / sizeof (par_cmd_bp[0]))); 373} 374 375/* 376 * di - disk insert 377 */ 378static 379void mon_cmd_di (monitor_t *mon, cmd_t *cmd) 380{ 381 int have_drive, ro; 382 unsigned drive; 383 char name[256], str[128]; 384 385 if (mon->setmsg == NULL) { 386 cmd_error (cmd, "monitor: no message function\n"); 387 return; 388 } 389 390 have_drive = 0; 391 ro = 0; 392 393 if (cmd_match_str (cmd, name, sizeof (name)) == 0) { 394 cmd_error (cmd, "need a file name\n"); 395 return; 396 } 397 398 while (1) { 399 if (cmd_match (cmd, "ro")) { 400 ro = 1; 401 } 402 else if (cmd_match (cmd, "rw")) { 403 ro = 0; 404 } 405 else if (cmd_match_uint (cmd, &drive, 10)) { 406 have_drive = 1; 407 } 408 else { 409 break; 410 } 411 } 412 413 if (!cmd_match_end (cmd)) { 414 return; 415 } 416 417 if (have_drive) { 418 sprintf (str, "%u", drive); 419 420 if (mon->setmsg (mon->msgext, "disk.id", str)) { 421 return; 422 } 423 } 424 425 if (mon->setmsg (mon->msgext, "disk.insert", name)) { 426 return; 427 } 428 429 if (ro) { 430 if (mon->setmsg (mon->msgext, "disk.ro", NULL)) { 431 return; 432 } 433 } 434} 435 436/* 437 * d - dump memory 438 */ 439static 440void mon_cmd_d (monitor_t *mon, cmd_t *cmd) 441{ 442 unsigned i, j; 443 unsigned long addr, addr2, cnt; 444 unsigned short ofs; 445 unsigned long p1, p2, o1; 446 unsigned char val, val1, val2; 447 char str1[64], str2[32]; 448 449 addr = mon->last_addr; 450 ofs = mon->last_ofs; 451 cnt = 256; 452 453 if (mon_match_address (mon, cmd, &addr, NULL, &ofs)) { 454 cmd_match_uint32 (cmd, &cnt); 455 } 456 457 if (!cmd_match_end (cmd)) { 458 return; 459 } 460 461 if (cnt == 0) { 462 return; 463 } 464 465 addr2 = (addr + cnt - 1) & 0xffffffff; 466 467 if (addr2 < addr) { 468 addr2 = 0xffffffff; 469 cnt = addr2 - addr + 1; 470 } 471 472 p1 = addr & 0xfffffff0; 473 p2 = (addr2 + 16) & 0xfffffff0; 474 o1 = ofs & 0xfff0; 475 476 while (p1 != p2) { 477 i = p1 & 15; 478 j = 3 * i; 479 480 if (i == 0) { 481 if (mon->memory_mode == 0) { 482 pce_printf ("%08lX", p1); 483 } 484 else { 485 pce_printf ("%04lX:%04lX", (p1 - o1) >> 4, o1); 486 } 487 } 488 489 str1[j] = (i == 8) ? '-' : ' '; 490 491 if ((p1 < addr) || (p1 > addr2)) { 492 str1[j + 1] = ' '; 493 str1[j + 2] = ' '; 494 str2[i] = ' '; 495 } 496 else { 497 val = mon_get_mem8 (mon, p1); 498 499 val1 = (val >> 4) & 0x0f; 500 val2 = val & 0x0f; 501 502 str1[j + 1] = (val1 < 10) ? ('0' + val1) : ('A' + val1 - 10); 503 str1[j + 2] = (val2 < 10) ? ('0' + val2) : ('A' + val2 - 10); 504 505 if ((val >= 32) && (val <= 127)) { 506 str2[i] = val; 507 } 508 else { 509 str2[i] = '.'; 510 } 511 } 512 513 if (((p1 + 1) & 15) == 0) { 514 str1[j + 3] = 0; 515 str2[i + 1] = 0; 516 517 pce_printf (" %s %s\n", str1, str2); 518 } 519 520 p1 = (p1 + 1) & 0xffffffff; 521 o1 = (o1 + 1) & 0xffff; 522 } 523 524 mon->last_addr = (addr + cnt) & 0xffffffff; 525 mon->last_ofs = (ofs + cnt) & 0xffff; 526} 527 528/* 529 * e - enter bytes into memory 530 */ 531static 532void mon_cmd_e (monitor_t *mon, cmd_t *cmd) 533{ 534 unsigned i; 535 unsigned long addr; 536 unsigned short val; 537 char str[256]; 538 539 if (!mon_match_address (mon, cmd, &addr, NULL, NULL)) { 540 cmd_error (cmd, "need an address"); 541 return; 542 } 543 544 while (1) { 545 if (cmd_match_uint16 (cmd, &val)) { 546 mon_set_mem8 (mon, addr, val); 547 addr += 1; 548 } 549 else if (cmd_match_str (cmd, str, 256)) { 550 i = 0; 551 while (str[i] != 0) { 552 mon_set_mem8 (mon, addr, str[i]); 553 addr += 1; 554 i += 1; 555 } 556 } 557 else { 558 break; 559 } 560 } 561 562 cmd_match_end (cmd); 563} 564 565/* 566 * f - find bytes in memory 567 */ 568static 569void mon_cmd_f (monitor_t *mon, cmd_t *cmd) 570{ 571 unsigned i, n; 572 unsigned short seg, ofs; 573 unsigned long addr, cnt; 574 unsigned short val; 575 unsigned char buf[256]; 576 char str[256]; 577 578 if (!mon_match_address (mon, cmd, &addr, &seg, &ofs)) { 579 cmd_error (cmd, "need an address"); 580 return; 581 } 582 583 if (!cmd_match_uint32 (cmd, &cnt)) { 584 cmd_error (cmd, "need a byte count"); 585 return; 586 } 587 588 n = 0; 589 590 while (n < 256) { 591 if (cmd_match_uint16 (cmd, &val)) { 592 buf[n++] = val; 593 } 594 else if (cmd_match_str (cmd, str, 256)) { 595 i = 0; 596 while ((n < 256) && (str[i] != 0)) { 597 buf[n++] = str[i++]; 598 } 599 } 600 else { 601 break; 602 } 603 } 604 605 if (!cmd_match_end (cmd)) { 606 return; 607 } 608 609 cnt = (cnt < n) ? 0 : (cnt - n); 610 611 while (cnt > 0) { 612 for (i = 0; i < n; i++) { 613 if (mon_get_mem8 (mon, addr + i) != buf[i]) { 614 break; 615 } 616 } 617 618 if (i >= n) { 619 if (mon->memory_mode == 0) { 620 pce_printf ("%08lX\n", addr); 621 } 622 else { 623 pce_printf ("%04X:%04X\n", seg, ofs); 624 } 625 } 626 627 ofs = (ofs + 1) & 0xffff; 628 629 if (ofs == 0) { 630 seg += 0x1000; 631 } 632 633 addr += 1; 634 635 cnt -= 1; 636 } 637} 638 639/* 640 * h - print help 641 */ 642static 643void mon_cmd_h (monitor_t *mon, cmd_t *cmd) 644{ 645 unsigned i, w1, w2, t; 646 647 w1 = 0; 648 w2 = 0; 649 650 for (i = 0; i < mon->cmd_cnt; i++) { 651 if ((t = strlen (mon->cmd[i].cmd)) > w1) { 652 w1 = t; 653 } 654 655 if ((t = strlen (mon->cmd[i].par)) > w2) { 656 w2 = t; 657 } 658 } 659 660 for (i = 0; i < mon->cmd_cnt; i++) { 661 pce_puts (mon->cmd[i].cmd); 662 663 t = strlen (mon->cmd[i].cmd); 664 665 while (t <= w1) { 666 pce_puts (" "); 667 t += 1; 668 } 669 670 pce_puts (mon->cmd[i].par); 671 672 t = strlen (mon->cmd[i].par); 673 674 while (t <= (w2 + 1)) { 675 pce_puts (" "); 676 t += 1; 677 } 678 679 pce_puts (mon->cmd[i].text); 680 pce_puts ("\n"); 681 } 682} 683 684/* 685 * load - read memory from disk 686 */ 687static 688void mon_cmd_load (monitor_t *mon, cmd_t *cmd) 689{ 690 int c; 691 unsigned fmt; 692 unsigned long addr, cnt; 693 char fname[256]; 694 FILE *fp; 695 696 if (!cmd_match_str (cmd, fname, 256)) { 697 cmd_error (cmd, "need a file name"); 698 return; 699 } 700 701 if (mon_match_format (mon, cmd, &fmt) == 0) { 702 fmt = mon_guess_format (fname); 703 } 704 705 if (fmt == MON_FORMAT_NONE) { 706 pce_printf ("can't guess file format (%s)\n", fname); 707 return; 708 } 709 710 if (fmt == MON_FORMAT_BINARY) { 711 if (!mon_match_address (mon, cmd, &addr, NULL, NULL)) { 712 cmd_error (cmd, "need an address"); 713 return; 714 } 715 716 if (!cmd_match_uint32 (cmd, &cnt)) { 717 cnt = 0; 718 } 719 } 720 721 if (!cmd_match_end (cmd)) { 722 return; 723 } 724 725 fp = fopen (fname, "rb"); 726 727 if (fp == NULL) { 728 pce_printf ("can't open file (%s)\n", fname); 729 return; 730 } 731 732 switch (fmt) { 733 case MON_FORMAT_BINARY: 734 while (1) { 735 if ((c = fgetc (fp)) == EOF) { 736 break; 737 } 738 739 mon_set_mem8 (mon, addr, c); 740 741 addr += 1; 742 743 if (cnt > 0) { 744 if (--cnt == 0) { 745 break; 746 } 747 } 748 } 749 break; 750 751 case MON_FORMAT_IHEX: 752 if (ihex_load_fp (fp, mon, (ihex_set_f) mon_set_mem8)) { 753 pce_printf ("loading ihex failed\n"); 754 } 755 break; 756 757 case MON_FORMAT_MHEX: 758 if (mhex_load_fp (fp, mon, (mhex_set_f) mon_set_mem8)) { 759 pce_printf ("loading mhex failed\n"); 760 } 761 break; 762 763 case MON_FORMAT_SREC: 764 if (srec_load_fp (fp, mon, (srec_set_f) mon_set_mem8)) { 765 pce_printf ("loading srec failed\n"); 766 } 767 break; 768 769 case MON_FORMAT_THEX: 770 if (thex_load_fp (fp, mon, (thex_set_f) mon_set_mem8)) { 771 pce_printf ("loading thex failed\n"); 772 } 773 break; 774 } 775 776 fclose (fp); 777} 778 779static 780void mon_cmd_m (monitor_t *mon, cmd_t *cmd) 781{ 782 char msg[256]; 783 char val[256]; 784 785 if (!cmd_match_str (cmd, msg, 256)) { 786 strcpy (msg, ""); 787 } 788 789 if (!cmd_match_str (cmd, val, 256)) { 790 strcpy (val, ""); 791 } 792 793 if (!cmd_match_end (cmd)) { 794 return; 795 } 796 797 if (mon->setmsg != NULL) { 798 if (mon->setmsg (mon->msgext, msg, val)) { 799 pce_puts ("error\n"); 800 } 801 } 802 else { 803 pce_puts ("monitor: no set message function\n"); 804 } 805} 806 807/* 808 * mem - set memory to r/w or r/o 809 */ 810static 811void mon_cmd_mem (monitor_t *mon, cmd_t *cmd) 812{ 813 if (cmd_match (cmd, "ro")) { 814 mon->rw = 0; 815 } 816 else if (cmd_match (cmd, "rw")) { 817 if (mon->set_mem8rw == NULL) { 818 pce_puts ("monitor: no rw function\n"); 819 } 820 else { 821 mon->rw = 1; 822 } 823 } 824 else { 825 pce_printf ("memory is %s\n", mon->rw ? "rw" : "ro"); 826 } 827 828 if (!cmd_match_end (cmd)) { 829 return; 830 } 831} 832 833/* 834 * save - write memory to disk 835 */ 836static 837void mon_cmd_save (monitor_t *mon, cmd_t *cmd) 838{ 839 unsigned fmt; 840 unsigned long addr, cnt; 841 unsigned short seg, ofs; 842 char fname[256]; 843 FILE *fp; 844 845 if (!cmd_match_str (cmd, fname, 256)) { 846 cmd_error (cmd, "need a file name"); 847 return; 848 } 849 850 if (mon_match_format (mon, cmd, &fmt) == 0) { 851 fmt = mon_guess_format (fname); 852 } 853 854 if (fmt == 0) { 855 pce_printf ("can't guess file format (%s)\n", fname); 856 return; 857 } 858 859 fp = fopen (fname, "wb"); 860 861 if (fp == NULL) { 862 pce_printf ("can't open file (%s)\n", fname); 863 return; 864 } 865 866 if (fmt == MON_FORMAT_THEX) { 867 thex_save_start (fp); 868 } 869 870 while (cmd_match_eol (cmd) == 0) { 871 if (!mon_match_address (mon, cmd, &addr, &seg, &ofs)) { 872 cmd_error (cmd, "need an address"); 873 break; 874 } 875 876 if (!cmd_match_uint32 (cmd, &cnt)) { 877 cmd_error (cmd, "need a byte count"); 878 break; 879 } 880 881 switch (fmt) { 882 case MON_FORMAT_BINARY: 883 while (cnt > 0) { 884 fputc (mon_get_mem8 (mon, addr), fp); 885 886 addr += 1; 887 cnt -= 1; 888 } 889 break; 890 891 case MON_FORMAT_IHEX: 892 if (mon->memory_mode == 0) { 893 if (ihex_save_linear (fp, addr, cnt, mon, (ihex_get_f) mon_get_mem8)) { 894 pce_printf ("saving ihex failed\n"); 895 } 896 } 897 else { 898 if (ihex_save (fp, seg, ofs, cnt, mon, (ihex_get_f) mon_get_mem8)) { 899 pce_printf ("saving ihex failed\n"); 900 } 901 } 902 break; 903 904 case MON_FORMAT_MHEX: 905 if (mon->memory_mode == 0) { 906 seg = 0; 907 ofs = addr; 908 } 909 910 if (mhex_save_fp (fp, seg, ofs, cnt, mon, (mhex_get_f) mon_get_mem8)) { 911 pce_printf ("saving mhex failed\n"); 912 } 913 break; 914 915 case MON_FORMAT_SREC: 916 if (srec_save (fp, addr, cnt, mon, (srec_get_f) mon_get_mem8)) { 917 pce_printf ("saving srec failed\n"); 918 } 919 break; 920 921 case MON_FORMAT_THEX: 922 if (mon->memory_mode == 0) { 923 if (thex_save (fp, addr, cnt, mon, (thex_get_f) mon_get_mem8)) { 924 pce_printf ("saving thex failed\n"); 925 } 926 } 927 else { 928 if (thex_save_seg (fp, seg, ofs, cnt, mon, (thex_get_f) mon_get_mem8)) { 929 pce_printf ("saving thex failed\n"); 930 } 931 } 932 break; 933 934 } 935 } 936 937 if (fmt == MON_FORMAT_IHEX) { 938 ihex_save_done (fp); 939 } 940 else if (fmt == MON_FORMAT_SREC) { 941 srec_save_done (fp); 942 } 943 else if (fmt == MON_FORMAT_THEX) { 944 thex_save_done (fp); 945 } 946 947 fclose (fp); 948} 949 950static 951void mon_cmd_redir_inp (monitor_t *mon, cmd_t *cmd) 952{ 953 int close; 954 char fname[256]; 955 956 close = 0; 957 958 if (!cmd_match_str (cmd, fname, 256)) { 959 close = 1; 960 } 961 962 if (!cmd_match_end (cmd)) { 963 return; 964 } 965 966 if (close) { 967 pce_set_redir_inp (NULL); 968 } 969 else { 970 if (pce_set_redir_inp (fname)) { 971 pce_puts ("error setting redirection\n"); 972 } 973 else { 974 pce_printf ("redirecting from \"%s\"\n", fname); 975 } 976 } 977} 978 979static 980void mon_cmd_redir_out (monitor_t *mon, cmd_t *cmd) 981{ 982 int close; 983 const char *mode; 984 char fname[256]; 985 986 close = 0; 987 mode = "w"; 988 989 if (cmd_match (cmd, ">")) { 990 mode = "a"; 991 } 992 993 if (!cmd_match_str (cmd, fname, 256)) { 994 close = 1; 995 } 996 997 if (!cmd_match_end (cmd)) { 998 return; 999 } 1000 1001 if (close) { 1002 pce_set_redir_out (NULL, NULL); 1003 } 1004 else { 1005 if (pce_set_redir_out (fname, mode)) { 1006 pce_puts ("error setting redirection\n"); 1007 } 1008 else { 1009 pce_printf ("redirecting to \"%s\"\n", fname); 1010 } 1011 } 1012} 1013 1014static 1015void mon_cmd_v (cmd_t *cmd) 1016{ 1017 unsigned long val; 1018 1019 if (cmd_match_eol (cmd)) { 1020 cmd_list_syms (cmd); 1021 return; 1022 } 1023 1024 while (cmd_match_uint32 (cmd, &val)) { 1025 pce_printf ("%lX\n", val); 1026 } 1027 1028 if (!cmd_match_end (cmd)) { 1029 return; 1030 } 1031} 1032 1033/* 1034 * y - copy memory 1035 */ 1036static 1037void mon_cmd_y (monitor_t *mon, cmd_t *cmd) 1038{ 1039 unsigned long i; 1040 unsigned long src, dst, cnt; 1041 unsigned char val; 1042 1043 if (!mon_match_address (mon, cmd, &src, NULL, NULL)) { 1044 cmd_error (cmd, "need a source address"); 1045 return; 1046 } 1047 1048 if (!mon_match_address (mon, cmd, &dst, NULL, NULL)) { 1049 cmd_error (cmd, "need a destination address"); 1050 return; 1051 } 1052 1053 if (!cmd_match_uint32 (cmd, &cnt)) { 1054 cmd_error (cmd, "need a byte count"); 1055 return; 1056 } 1057 1058 if (!cmd_match_end (cmd)) { 1059 return; 1060 } 1061 1062 if (cnt == 0) { 1063 return; 1064 } 1065 1066 if (src >= dst) { 1067 for (i = 0; i < cnt; i++) { 1068 val = mon_get_mem8 (mon, src + i); 1069 mon_set_mem8 (mon, dst + i, val); 1070 } 1071 } 1072 else { 1073 src += cnt - 1; 1074 dst += cnt - 1; 1075 1076 for (i = 0; i < cnt; i++) { 1077 val = mon_get_mem8 (mon, src - i); 1078 mon_set_mem8 (mon, dst - i, val); 1079 } 1080 } 1081} 1082 1083 1084int mon_run (monitor_t *mon) 1085{ 1086 int r; 1087 cmd_t cmd; 1088 1089 while (mon->terminate == 0) { 1090 if (mon->setmsg != NULL) { 1091 mon->setmsg (mon->msgext, "term.release", "1"); 1092 mon->setmsg (mon->msgext, "term.fullscreen", "0"); 1093 } 1094 1095 cmd_get (&cmd, mon->prompt); 1096 1097 if (cmd_match (&cmd, ";")) { 1098 continue; 1099 } 1100 1101 r = 1; 1102 1103 if (cmd_match (&cmd, "load")) { 1104 mon_cmd_load (mon, &cmd); 1105 } 1106 else if (cmd_match (&cmd, "save")) { 1107 mon_cmd_save (mon, &cmd); 1108 } 1109 else if (mon->docmd != NULL) { 1110 r = mon->docmd (mon->cmdext, &cmd); 1111 } 1112 1113 if (r != 0) { 1114 if (cmd_match (&cmd, "di")) { 1115 mon_cmd_di (mon, &cmd); 1116 } 1117 else if (cmd_match (&cmd, "d")) { 1118 mon_cmd_d (mon, &cmd); 1119 } 1120 else if (cmd_match (&cmd, "e")) { 1121 mon_cmd_e (mon, &cmd); 1122 } 1123 else if (cmd_match (&cmd, "f")) { 1124 mon_cmd_f (mon, &cmd); 1125 } 1126 else if (cmd_match (&cmd, "h")) { 1127 mon_cmd_h (mon, &cmd); 1128 } 1129 else if (cmd_match (&cmd, "mem")) { 1130 mon_cmd_mem (mon, &cmd); 1131 } 1132 else if (cmd_match (&cmd, "m")) { 1133 mon_cmd_m (mon, &cmd); 1134 } 1135 else if (cmd_match (&cmd, "q")) { 1136 break; 1137 } 1138 else if (cmd_match (&cmd, "v")) { 1139 mon_cmd_v (&cmd); 1140 } 1141 else if (cmd_match (&cmd, "y")) { 1142 mon_cmd_y (mon, &cmd); 1143 } 1144 else if (cmd_match (&cmd, "<")) { 1145 mon_cmd_redir_inp (mon, &cmd); 1146 } 1147 else if (cmd_match (&cmd, ">")) { 1148 mon_cmd_redir_out (mon, &cmd); 1149 } 1150 else if (!cmd_match_eol (&cmd)) { 1151 cmd_error (&cmd, "unknown command"); 1152 } 1153 } 1154 }; 1155 1156 return (0); 1157}