fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
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}