1 /* MAIN PART OF MONITOR */
2
3 #include <unistd.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include "z80-cpu.h"
9 #include "execute.h"
10 #include "console_token"
11 #include "console.h"
12 #include "regs.h"
13 #include "file.h"
14 #include "asm.h"
15 #include "decode.h"
16 #include "memory.h"
17 #include "ports.h"
18 #include "interrupt.h"
19 #include "mini-display.h"
20 #include "keyboard.h"
21 #include "hash.h"
22 #include "expression.h"
23 #include "hardware/includes"
24
25 static _ushort MEMP;
26
27 static char *msg1="Z80 monitor V 2.3\n(c)1999-2004 Brainsoft\n";
28 static char *msg2="Z80 monitor (GPL) " TIME_STAMP;
29 static char _string[257];
30 static char *string= _string+1;
31 static char load_name[256];
32 static char save_name[256];
33 static char proto_name[256];
34 static FILE *stream;
35
36 static unsigned speed;
37 static int keyboard_disabled;
38 static int current_pc;
39 static int follow;
40 static int row; /* row for printing next instruction */
41 static _uchar tmp_memory[64];
42 static unsigned long last_ticks;
43 static unsigned long breakpt[8];
44
45 struct info{ char *label; int value; unsigned lineno; };
46 static struct info *ele;
47 static unsigned labels, next_label_index;
48
49 enum
50 { DEFAULT,TOKEN,ADDR, HOT,GARISH,WARN, MEMORY,STATUS,HIDDEN };
51 static unsigned char color[] =
52 { WHITE, GREEN,YELLOW,RED,BRIGHT,YELLOW,BLUE, PURPLE,GRAY };
53
54 #define KEYBOARD_MAP_FILE "keyboard_map"
55
56
warning(char * message)57 static void warning(char* message)
58 {
59 static char txt[512];
60 /* c_bell(); */
61 c_goto(0,23);
62 c_setcolor(color[WARN]);
63 sprintf(txt,"%s",message);
64 c_print(txt);
65 usleep(2000000L);
66 c_setcolor(color[DEFAULT]);
67 c_clear(0,23,79,23);
68 }
69
70
error_msg(char * line,char * message)71 static void error_msg(char *line,char* message)
72 {
73 static char txt[512];
74 c_bell();
75 c_goto(0,23);
76 c_setcolor(color[HOT]);
77 sprintf(txt,"Error: %s %s",message,line);
78 c_print(txt);
79 usleep(1000000L);
80 c_setcolor(color[DEFAULT]);
81 c_clear(0,23,79,23);
82 }
83
84
85 /*** called e.g. from decode(...) in simul.c or compile() defined in asm.c ***/
error(int n,const char * line,char * message)86 void error(int n,const char *line,char* message)
87 {
88 static char txt[512];
89 unsigned char k;
90 n=n;
91 c_bell();
92 c_goto(0,22);
93 c_print(line);
94 c_goto(0,23);
95 c_setcolor(color[HOT]);
96 sprintf(txt,"Error: %s",message);
97 c_print(txt);
98 c_setcolor(color[DEFAULT]);
99 c_print(" hit any key");
100 k=c_getkey();
101 c_clear(0,22,39,22);
102 c_clear(0,23,79,23);
103 }
104
105
106 static char
__printable(char c)107 __printable(char c)
108 {
109 return (c>=32&&c<127)?c:'.';
110 }
111
112
113 /* prints instruction */
114 void
print(char * str)115 print(char *str)
116 {
117 if (row >= 0)
118 {
119 char txt[256];
120 sprintf(txt," %04x ",current_pc);
121 c_goto(0,row);
122 c_setcolor(row==12?color[GARISH]:color[ADDR]);
123 c_print(txt);
124 c_setcolor(row==12?color[GARISH]:color[DEFAULT]);
125 c_print(str);
126 }
127 else if (row == -1)
128 fprintf(stream,"%04x %-14s",current_pc,str);
129 else if (row == -2 && (MODE&16))
130 ; /* first pass disassembling */
131 else if (row == -2)
132 { int i;
133 fprintf(stream,"%04x ",current_pc);
134 for (i=0; i < (PC?PC:65536)-current_pc && i<4; i++)
135 fprintf(stream,"%02x ",(unsigned)memory_at((_ushort)(current_pc+i)));
136 for (;i<4;i++)
137 fprintf(stream," ");
138 for (i=0; i < (PC?PC:65536)-current_pc && i<4; i++)
139 { unsigned char m=memory_at((_ushort)(current_pc+i));
140 fprintf(stream,"%c",(m>=32&&m<127?m:' '));
141 }
142 for (;i<4;i++)
143 fprintf(stream," ");
144 if (MODE&8) /* second pass disassembling */
145 { while (next_label_index < labels && ele[next_label_index].value < current_pc)
146 next_label_index++;
147 if (next_label_index >= labels || ele[next_label_index].value > current_pc)
148 fprintf(stream," ");
149 else
150 {
151 fprintf(stream," %5s: ",ele[next_label_index].label);
152 ele[next_label_index].label[0]=0;
153 next_label_index += 1;
154 while (next_label_index < labels &&
155 ele[next_label_index].value == ele[next_label_index-1].value)
156 ele[next_label_index].label[0]=0;
157 }
158 }
159 fprintf(stream," %-s",str);
160 }
161 }
162
163
164 static void
__print_r16(int x,int y,char * t,int R)165 __print_r16(int x,int y,char *t,int R)
166 {
167 char txt[256];
168 c_goto(x,y);
169 sprintf(txt,"%s=",t);
170 c_setcolor(color[TOKEN]);
171 c_print(txt);
172 sprintf(txt,"0x%04x %05u",R,R);
173 c_setcolor(color[DEFAULT]);
174 c_print(txt);
175 }
176
177
178 static void
__print_rr(int x,int y,char * t,int R)179 __print_rr(int x,int y,char *t,int R)
180 {
181 char txt[256];
182 c_goto(x,y);
183 sprintf(txt,"%s=",t);
184 c_setcolor(color[TOKEN]);
185 c_print(txt);
186 sprintf(txt,"x%02xx%02x %05u",R>>8&255,R&255,R);
187 c_setcolor(color[DEFAULT]);
188 c_print(txt);
189 }
190
191
192 static void
tobin(char * s,_uchar x)193 tobin(char *s,_uchar x)
194 {
195 int a;
196 for (a=0;a<8;a++)
197 s[7-a]=((x&(1<<a))>>a)?'1':'0';
198 s[8]=0;
199 }
200
201
202 static void
__print_x(int x,int y,char * t,_uchar R)203 __print_x(int x,int y,char *t,_uchar R)
204 {
205 char txt[256];
206 char b[256];
207 tobin(b,R);
208 c_goto(x,y);
209 sprintf(txt,"%s=",t);
210 c_setcolor(color[TOKEN]);
211 c_print(txt);
212 sprintf(txt,"x%02x (%s)",(unsigned)R,b);
213 c_setcolor(color[DEFAULT]);
214 c_print(txt);
215 }
216
217
218 static void
__print_r(int x,int y,char * t,_uchar R)219 __print_r(int x,int y,char *t,_uchar R)
220 {
221 char txt[256];
222 char b[256];
223 tobin(b,R);
224 c_goto(x,y);
225 c_setcolor(color[TOKEN]);
226 sprintf(txt,"%s=",t);
227 c_print(txt);
228 c_setcolor(color[DEFAULT]);
229 sprintf(txt,"%03d",R);
230 c_print(txt);
231 c_setcolor(color[MEMORY]);
232 sprintf(txt,"%c",__printable(R));
233 c_print(txt);
234 c_setcolor(color[DEFAULT]);
235 sprintf(txt,"(%s)",b);
236 c_print(txt);
237 }
238
239
240 static void
print_generell_regs(void)241 print_generell_regs(void)
242 {
243 __print_rr(46,2,"AF",(A<<8)+F);
244 __print_rr(46,3,"BC",(B<<8)+C);
245 __print_rr(46,4,"DE",(D<<8)+E);
246 __print_rr(46,5,"HL",(H<<8)+L);
247
248 __print_rr(63,2,"AF'",(A_<<8)+F_);
249 __print_rr(63,3,"BC'",(B_<<8)+C_);
250 __print_rr(63,4,"DE'",(D_<<8)+E_);
251 __print_rr(63,5,"HL'",(H_<<8)+L_);
252
253 __print_r(46,12,"A",A);
254 __print_r(46,13,"F",F);
255 __print_r(46,14,"B",B);
256 __print_r(46,15,"C",C);
257 __print_r(46,16,"D",D);
258 __print_r(46,17,"E",E);
259 __print_r(46,18,"H",H);
260 __print_r(46,19,"L",L);
261
262 __print_r(63,12,"A'",A_);
263 __print_r(63,13,"F'",F_);
264 __print_r(63,14,"B'",B_);
265 __print_r(63,15,"C'",C_);
266 __print_r(63,16,"D'",D_);
267 __print_r(63,17,"E'",E_);
268 __print_r(63,18,"H'",H_);
269 __print_r(63,19,"L'",L_);
270
271 }
272
273
274 static void
print_index_regs(void)275 print_index_regs(void)
276 {
277 __print_r16(56,7,"IX",IX);
278 __print_r16(56,8,"IY",IY);
279 }
280
281
282 static void
print_sp_and_pc(void)283 print_sp_and_pc(void)
284 {
285 __print_r16(56,9,"SP",SP);
286 __print_r16(56,10,"PC",PC);
287 }
288
289
290 static void
print_special_regs(void)291 print_special_regs(void)
292 {
293 __print_x(47,21,"I",I);
294 __print_x(64,21,"R",R);
295 }
296
297
298 static void
print_regs(void)299 print_regs(void)
300 {
301 print_generell_regs();
302 print_index_regs();
303 print_sp_and_pc();
304 print_special_regs();
305 }
306
307
308 static void
print_flags(void)309 print_flags(void)
310 {
311 char txt[256];
312
313 c_goto(45,0);
314 c_setcolor(is_flag(F_C)?color[GARISH]:color[DEFAULT]);
315 c_print(is_flag(F_C)?" C ":"NC ");
316 c_setcolor(is_flag(F_Z)?color[GARISH]:color[DEFAULT]);
317 c_print(is_flag(F_Z)?" Z ":"NZ ");
318 c_setcolor(is_flag(F_M)?color[GARISH]:color[DEFAULT]);
319 c_print(is_flag(F_P)?" P ":" M ");
320 c_setcolor(is_flag(F_PE)?color[GARISH]:color[DEFAULT]);
321 c_print(is_flag(F_PE)?"PE ":"PO ");
322 c_setcolor(is_flag(F_H)?color[GARISH]:color[DEFAULT]);
323 c_print(is_flag(F_H)?" H ":"NH ");
324 c_setcolor(is_flag(F_N)?color[GARISH]:color[DEFAULT]);
325 c_print(is_flag(F_N)?" N ":"NN ");
326
327 c_setcolor(color[TOKEN]);
328 c_goto(73,0);
329 c_print("IM=");
330 sprintf(txt,"%d",IM);
331 c_setcolor(color[DEFAULT]);
332 c_goto(76,0);
333 c_print(txt);
334
335 c_setcolor(color[TOKEN]);
336 c_goto(65,0);
337 c_print("IFF=");
338 c_goto(69,0);
339 c_setcolor(IFF1?color[GARISH]:color[DEFAULT]);
340 c_print(IFF1?"EI":"DI");
341 c_setcolor(color[DEFAULT]);
342
343 }
344
345
346 static void
print_instr(void)347 print_instr(void)
348 {
349 _ushort old_pc=PC;
350
351 c_clear(7,12,22,22);
352 for (row=12;row<22;row++)
353 {
354 current_pc=PC;
355 decode(0,0);
356 }
357 c_goto(7,11);
358 c_setcolor(color[TOKEN]);
359 c_print("MNEMONIC");
360 c_setcolor(color[HIDDEN]);
361 if ((MODE&3)==1) c_print("d");
362 else if ((MODE&3)==2) c_print("h");
363 else if ((MODE&3)==3) c_print("x");
364 else c_print(" ");
365 if ((MODE&12)==4) c_print("a");
366 else if ((MODE&12)==8) c_print("l");
367 else if ((MODE&12)==12) c_print("L");
368 else c_print("r");
369 c_goto(0,12);
370 c_setcolor(color[GARISH]);
371 c_print(">");
372 c_setcolor(color[DEFAULT]);
373 PC=old_pc;
374 }
375
376
377 static void
print_stack(void)378 print_stack(void)
379 {
380 char txt[256];
381 _ushort b,c,d;
382 int r,a;
383
384 c_goto(30,11);
385 c_setcolor(color[TOKEN]);
386 c_print("STACK");
387 c_setcolor(color[DEFAULT]);
388 for (r=12,a=SP+12;a>=SP-6;a-=2,r++)
389 {
390 c=a&65535;
391 d=(a+1)&65535;
392 b=memory_at(c)|(memory_at(d)<<8);
393 sprintf(txt,"%04x ",c);
394 c_goto(24,r);
395 c_setcolor(r==18?color[GARISH]:color[ADDR]);
396 c_print(txt);
397 c_setcolor(r==18?color[GARISH]:color[DEFAULT]);
398 sprintf(txt,"%05d %04x ",b,b);
399 c_print(txt);
400 sprintf(txt,"%c%c",__printable(memory_at(d)),__printable(memory_at(c)));
401 c_setcolor(color[MEMORY]);
402 c_print(txt);
403 c_setcolor(color[DEFAULT]);
404 }
405 c_goto(23,18);
406 c_setcolor(color[GARISH]);
407 c_print(">");
408 c_setcolor(color[DEFAULT]);
409 }
410
411
412 static void
print_mem(void)413 print_mem(void)
414 {
415 char txt[256];
416 _ushort a;
417 int r,c;
418 _ushort memp;
419
420 if (follow)memp=PC;
421 else memp=MEMP;
422
423 c_goto(14,0);
424 c_setcolor(color[TOKEN]);
425 c_print("MEMORY");
426 for (r=0,c=memp;c<memp+80;c+=8,r++)
427 {_ushort b;
428 a=c&65535;
429 sprintf(txt,"%04x ",a);
430 c_goto(0,1+r);
431 c_setcolor(color[ADDR]);
432 c_print(txt);
433 c_setcolor(color[DEFAULT]);
434 for (b=0;b<8;b++)
435 sprintf(txt+3*b,"%02x ",(unsigned)memory_at(a+b));
436 c_print(txt);
437 for (b=0;b<8;b++)
438 sprintf(txt+b,"%c", __printable(memory_at(a+b)) );
439 c_setcolor(color[MEMORY]);
440 c_print(txt);
441 c_setcolor(color[DEFAULT]);
442 }
443 }
444
445
446 static void
print_speed(void)447 print_speed(void)
448 {
449 c_setcolor(color[STATUS]);
450 c_goto(11,23);
451 if (speed)
452 { char txt[12];
453 double freq= speed*0.0025;
454 if (freq < 1.0)
455 sprintf(txt," %4.0f kHz ",speed*2.5);
456 else if (freq < 10.0)
457 sprintf(txt,"%5.3f MHz ",freq);
458 else
459 sprintf(txt,"%5.2f MHz ",freq);
460 c_print(txt);
461 }
462 else
463 c_print(" ");
464 c_setcolor(color[DEFAULT]);
465 }
466
467
468 static void
print_status(void)469 print_status(void)
470 {
471 c_goto(0,23);
472 c_setcolor(color[STATUS]);
473 c_print(follow?"FOLLOW ":" ");
474 c_goto(7,23);
475 c_print(!cpu_is_in_disassemble?"RUN ":" ");
476 print_speed();
477 c_setcolor(color[STATUS]);
478 c_goto(20,23);
479 c_print(stream?"PROTO ":" ");
480 c_setcolor(color[HOT]);
481 c_goto(26,23);
482 c_print(keyboard_disabled?"NOKEYS":" ");
483 c_setcolor(color[DEFAULT]);
484 }
485
486
487 void
print_ticks(void)488 print_ticks(void)
489 {
490 char txt[16];
491 sprintf(txt,"%10lu",ticks);
492 c_setcolor(color[DEFAULT]);
493 c_goto(41,10);
494 c_print(txt);
495 c_setcolor(cpu_pin[busack]?color[HOT]:color[TOKEN]);
496 c_print(" T");
497 last_ticks=ticks;
498 sprintf(txt,"%10lu",cycles);
499 c_setcolor(color[DEFAULT]);
500 c_goto(41,8);
501 c_print(txt);
502 c_setcolor(color[TOKEN]);
503 c_print(" M");
504 }
505
506
507 static void
print_breaks(void)508 print_breaks(void)
509 {
510 int i,j;
511 char txt[16];
512 for (j=i=0;i<8;i++)
513 if (breakpt[i]>>16)
514 {
515 sprintf(txt,"%4lu",breakpt[i]>>16);
516 c_setcolor(color[HOT]);
517 c_goto(10*j,22);
518 c_print(txt);
519 sprintf(txt,"%04x",(unsigned)breakpt[i]&65535);
520 c_setcolor(color[ADDR]);
521 c_print(txt);
522 j++;
523 c_setcolor(color[DEFAULT]);
524 }
525 }
526
527
print_halt(void)528 static void print_halt(void)
529 {
530 c_setcolor(color[HOT]);
531 c_goto(78,0);
532 c_print(cpu_pin[halt]?"H":" ");
533 c_setcolor(color[DEFAULT]);
534 }
535
536
537 /* draw screen */
538 static void
print_panel(void)539 print_panel(void)
540 {
541 print_regs();
542 print_flags();
543 print_instr();
544 print_stack();
545 print_mem();
546 print_status();
547 print_ticks();
548 print_breaks();
549 print_halt();
550 }
551
552
553 static void
show_keys(void)554 show_keys(void)
555 {
556 int i=0;
557 c_cls();
558 #include "help_layout"
559 c_goto(0,23);
560 c_print("PRESS ANY KEY TO QUIT HELP.");
561 c_goto(79-strlen(msg2),23);
562 c_print(msg2);
563 c_getkey();
564 c_cls();
565 }
566
567
568 /* clear all general purpos registers and IX, IY, and SP */
569 static void
clear_user_regs(void)570 clear_user_regs(void)
571 {
572 A=0;B=0;C=0;D=0;E=0;F=0;H=0;L=0;
573 A_=0;B_=0;C_=0;D_=0;E_=0;F_=0;H_=0;L_=0;
574 SP=0;IX=0;IY=0;
575 }
576
577
578 /* put SP to 0xFFFC and store 4 bytes starting at 0xFFFC */
579 static void
stack_halt(void)580 stack_halt(void)
581 {
582 _ushort d;
583 SP=0xfffc;
584 d=SP+2;
585 write_memo(SP, d&255);
586 write_memo(SP+1, d>>8);
587 write_memo(SP+2,0xf3); /* DI */
588 write_memo(SP+3,0x76); /* HALT */
589 }
590
591
592 static void
ask_flag(void)593 ask_flag(void)
594 {
595 unsigned char c;
596 c_clear(0,23,79,23);
597 c_goto(0,23);
598 c_print("Toggle flag: Zero, Carry, Parity, Sign, H, N?");
599 c=c_getkey();
600 switch(c)
601 {
602 case 'z':
603 case 'Z':
604 set_flag(is_flag(F_Z)?F_NZ:F_Z);
605 break;
606
607 case 'c':
608 case 'C':
609 set_flag(is_flag(F_C)?F_NC:F_C);
610 break;
611
612 case 'p':
613 case 'P':
614 set_flag(is_flag(F_PE)?F_PO:F_PE);
615 break;
616
617 case 's':
618 case 'S':
619 set_flag(is_flag(F_M)?F_P:F_M);
620 break;
621
622 case 'h':
623 case 'H':
624 set_flag(is_flag(F_H)?F_NH:F_H);
625 break;
626
627 case 'n':
628 case 'N':
629 set_flag(is_flag(F_N)?F_NN:F_N);
630 break;
631
632 default:
633 c_bell();
634 break;
635 }
636 c_clear(0,23,79,23);
637 }
638
639
640 /* reads string from input (will be stored in pointer), writes prompt message */
641 /* string cannot be longer than max_len */
642 /* return value: 0=ok, 1=escape pressed */
643 static int
ask_str(char * pointer,char * message,int max_len)644 ask_str(char *pointer,char *message,int max_len)
645 {
646 unsigned char c;
647 int a=strlen(pointer),l=strlen(message);
648
649 c_clear(0,23,79,23);
650 c_cursor(C_NORMAL);
651 c_goto(0,23);
652 c_setcolor(color[GARISH]);
653 c_print(message);
654 c_setcolor(color[DEFAULT]);
655 c_print(pointer);
656 while(1)
657 {
658 c=c_getkey();
659 if (c==K_ESCAPE)
660 {
661 pointer[0]=0;
662 c_clear(0,23,79,23);
663 c_cursor(C_HIDE);
664 return 1;
665 }
666 if (c==K_ENTER)
667 {
668 c_clear(0,23,79,23);
669 c_cursor(C_HIDE);
670 return 0;
671 }
672 if (c==K_BACKSPACE&&a)
673 {
674 a--;
675 pointer[a]=0;
676 c_clear(l+strlen(pointer),23,79,23);
677 c_goto(l+strlen(pointer),23);
678 continue;
679 }
680 if (c>=32&&a<max_len)
681 {
682 pointer[a]=c; /* do charu se dava unsigned char */
683 a++;
684 pointer[a]=0;
685 c_goto(l,23);
686 c_print(pointer);
687 c_clear(l+strlen(pointer),23,79,23);
688 c_goto(l+strlen(pointer),23);
689 }
690 }
691 }
692
693
694 /* tries to convert a string to an unsigned number */
695 /* on error returns ~0 */
convert_to_uns(char * txt)696 static unsigned convert_to_uns(char *txt)
697 {
698 unsigned i, j, val;
699 for (i=0;txt[i]==' '||txt[i]=='\t';i++);
700 if (!txt[i] || txt[i]=='+' || txt[i]=='-') return ~0;
701 j=test_number(txt+i,&val); /* Single character-representation '?' is allowed */
702 if (!j) return ~0;
703 return val;
704 }
705
706
707 /* reads a non negative integer from input */
708 /* on escape or error returns ~0 */
709 static unsigned
ask(char * str,unsigned init_val)710 ask(char *str,unsigned init_val)
711 {
712 static char txt[256];
713
714 if (init_val)sprintf(txt,"%u",init_val);
715 else txt[0]=0;
716 if (ask_str(txt,str,16))return ~0;
717 return convert_to_uns(txt);
718 }
719
720
721 /* reads a non negative integer from input */
722 /* on escape or error returns ~0 */
723 static unsigned
ask_x(char * str,unsigned init_val)724 ask_x(char *str,unsigned init_val)
725 {
726 static char txt[256];
727
728 if (init_val)sprintf(txt,"0x%x",init_val);
729 else txt[0]=0;
730 if (ask_str(txt,str,16))return ~0;
731 return convert_to_uns(txt);
732 }
733
734
735 static void
ask_general_16_register(char * prompt,_uchar * high,_uchar * low)736 ask_general_16_register(char *prompt, _uchar *high, _uchar *low)
737 { unsigned x;
738 x=ask(prompt,*high<<8|*low);
739 if (x>65535)
740 { c_bell();print_status(); }
741 else
742 { *high= x>>8;
743 *low= x&255;
744 cpu_is_in_disassemble=1;
745 }
746 }
747
748
749 static void
ask_special_16_register(char * prompt,_ushort * reg16)750 ask_special_16_register(char *prompt, _ushort *reg16)
751 { unsigned x;
752 x=ask(prompt,*reg16);
753 if (x>65535)
754 { c_bell();print_status(); }
755 else
756 { *reg16= x;
757 cpu_is_in_disassemble=1;
758 }
759 }
760
761
762 static void
ask_16bit_register(void)763 ask_16bit_register(void)
764 {
765 unsigned char c;
766 c_clear(0,23,79,23);
767 do {
768 c_goto(0,23);
769 c_print("Toggle Register: bc, de, hl, BC, DE, HL, xX, yY, Sp");
770 c=c_getkey();
771 switch(c)
772 {
773 case 'b': ask_general_16_register("BC=",&B,&C);
774 break;
775
776 case 'B': ask_general_16_register("BC'=",&B_,&C_);
777 break;
778
779 case 'd': ask_general_16_register("DE=",&D,&E);
780 break;
781
782 case 'D': ask_general_16_register("DE'=",&D_,&E_);
783 break;
784
785 case 'h': ask_general_16_register("HL=",&H,&L);
786 break;
787
788 case 'H': ask_general_16_register("HL'=",&H_,&L_);
789 break;
790
791 case 'x': case 'X':
792 ask_special_16_register("IX=",&IX);
793 break;
794
795 case 'y': case 'Y':
796 ask_special_16_register("IY=",&IY);
797 break;
798
799 case 's': case 'S':
800 ask_special_16_register("SP=",&SP);
801 break;
802
803 case K_ENTER:
804 break;
805
806 default: c_bell();
807 break;
808 }
809 print_regs();
810 } while (c != K_ENTER);
811 c_clear(0,23,79,23);
812 }
813
814
815 static void
ask_8bit_register(char * prompt,_uchar * reg8)816 ask_8bit_register(char *prompt, _uchar *reg8)
817 {
818 unsigned x=ask(prompt,*reg8);
819 if (x>255)
820 { c_bell();print_status(); }
821 else
822 { *reg8= x;
823 cpu_is_in_disassemble=1;
824 }
825 }
826
827
828 static void
ask_register(void)829 ask_register(void)
830 {
831 unsigned char c;
832 c_clear(0,23,79,23);
833 do {
834 c_goto(0,23);
835 c_print("Toggle Register: a, f, b, c, d, e, h, l, "
836 "A, F, B, C, D, E, H, L, =, I, R");
837 c=c_getkey();
838 switch(c)
839 {
840 case '=': ask_16bit_register();
841 break;
842
843 case 'a': ask_8bit_register("A=",&A);
844 break;
845
846 case 'A': ask_8bit_register("A'=",&A_);
847 break;
848
849 case 'f': ask_8bit_register("F=",&F);
850 print_flags();
851 break;
852
853 case 'F': ask_8bit_register("F'=",&F_);
854 print_flags();
855 break;
856
857 case 'b': ask_8bit_register("B=",&B);
858 break;
859
860 case 'B': ask_8bit_register("B'=",&B_);
861 break;
862
863 case 'c': ask_8bit_register("C=",&C);
864 break;
865
866 case 'C': ask_8bit_register("C'=",&C_);
867 break;
868
869 case 'd': ask_8bit_register("D=",&D);
870 break;
871
872 case 'D': ask_8bit_register("D'=",&D_);
873 break;
874
875 case 'e': ask_8bit_register("E=",&E);
876 break;
877
878 case 'E': ask_8bit_register("E'=",&E_);
879 break;
880
881 case 'h': ask_8bit_register("H=",&H);
882 break;
883
884 case 'H': ask_8bit_register("H'=",&H_);
885 break;
886
887 case 'l': ask_8bit_register("L=",&L);
888 break;
889
890 case 'L': ask_8bit_register("L'=",&L_);
891 break;
892
893 case 'I': ask_8bit_register("I=",&I);
894 break;
895
896 case 'R': ask_8bit_register("R=",&R);
897 break;
898
899 case K_ENTER:
900 break;
901
902 default: c_bell();
903 break;
904 }
905 print_regs();
906 } while (c != K_ENTER);
907 c_clear(0,23,79,23);
908 }
909
910
911 static void
protocol(void)912 protocol(void)
913 {
914 row = -1;
915 current_pc=PC;
916 decode(0,0);
917 fprintf(stream,"%c%c%c%c ",(is_flag(F_C)?'C':'.'),(is_flag(F_Z)?'Z':'.')
918 ,(is_flag(F_M)?'-':'+'),(is_flag(F_PE)?'e':'o'));
919 fprintf(stream,"%02x %02x %02x %02x %02x %02x %02x ",A,B,C,D,E,H,L);
920 fprintf(stream,"%02x %02x %02x %02x %02x %02x %02x ",A_,B_,C_,D_,E_,H_,L_);
921 fprintf(stream,"%04x %04x %04x\n",IX,IY,SP);
922 fflush(stream);
923 PC=current_pc;
924 }
925
926
finish(int signo)927 void finish(int signo)
928 {
929 c_shutdown();
930 exit(-signo);
931 }
932
933
compare_addr(const struct info * left,const struct info * right)934 static int compare_addr(const struct info *left, const struct info *right)
935 {
936 return left->value == right->value ? 0 : left->value < right->value ? -1:1;
937 }
938
939
940 /*-------------------------------MAIN-----------------------------------------*/
941 int
main(int argc,char ** argv)942 main(int argc,char **argv)
943 {
944 unsigned char c, rom_path[256], bank_mapping_descr[128], emu=0;
945 unsigned short old_pc;
946 int b,a,s;
947 unsigned short start;
948 unsigned x;
949
950 string[-1]=' '; /* that is ok! (prevents any label recognation in compile) */
951 strcpy(rom_path,".");
952 strcpy(bank_mapping_descr,"");
953
954 for (b=s=1;s<argc && *argv[s]=='-';s++,b=1)
955 {
956 if (!*(argv[s]+b))
957 continue;
958 else if (*(argv[s]+b)=='E')
959 emu=1;
960 else if (*(argv[s]+b)=='B')
961 { if (s+1>=argc || 1!=sscanf(argv[s+1],"%127s",bank_mapping_descr))
962 fprintf(stderr,"Error: option -B needs a filename argument\n");
963 else
964 b=0, s++;
965 }
966 else if (*(argv[s]+b)=='R')
967 { if (s+1>=argc || 1!=sscanf(argv[s+1],"%255s",rom_path))
968 fprintf(stderr,"Error: option -R needs a path argument\n");
969 else
970 b=0, s++;
971 }
972 else if (*(argv[s]+b)=='h' || *(argv[s]+b)=='?')
973 {
974 printf("%s\n",msg1);
975 printf("Usage: z80-mon [-h] [-E] [-R path] [<filename> ...]\n");
976 return 0;
977 }
978 }
979 clear_memory();
980 MEMP=0;
981
982 for (b=s;b<argc;b++)
983 {
984 stream=fopen(argv[b],"rb");
985 if (!stream){fprintf(stderr,"Error: Can't read file \"%s\".\n",argv[b]);return(1);}
986 if (read_header(stream,&start,&x)){fprintf(stderr,"Error: \"%s\" is not a Z80 ASM file.\n",argv[b]);return(1);}
987 dma_write(start,x,stream);
988 MEMP=start;
989 fclose(stream);
990 stream=0;
991 }
992
993 c_init(BLACK); /** for DEBUG set it to WHITE **/
994 c_cursor(C_HIDE);
995 define_scroll_line(39,23,40);
996 init_keyboard_map(KEYBOARD_MAP_FILE);
997 if(init_ports())
998 warning("asynchron buffered CPU port access impossible");
999 else if (*bank_mapping_descr)
1000 init_banks(rom_path,bank_mapping_descr);
1001 if (emu)
1002 { init_cpu(".CPU");
1003 cpu_is_in_disassemble=0;
1004 speed= 1<<12;
1005 keyboard_disabled=1;
1006 follow=0;
1007 }
1008 else
1009 {
1010 #ifdef Z80_CTC
1011 if (init_ctc())
1012 error_msg("asynchron CTC port access denied","system:");
1013 #endif
1014 #ifdef LOGIC_ANALYZER
1015 reset_analyzer(".bus_proto");
1016 #endif
1017 reset_cpu();
1018 follow=1;
1019 }
1020 last_ticks=0;
1021 io_address=NULL;
1022
1023 disable_pseudo=0;
1024 init_interrupt_handling();
1025 print_panel();
1026
1027 while (1)
1028 {
1029 if (cpu_pin[halt] && !IFF1)
1030 { if (!cpu_is_in_disassemble && emu)
1031 { dump_cpu(".CPU");
1032 break;
1033 }
1034 else
1035 cpu_is_in_disassemble= 1;
1036 }
1037 if (cpu_pin[busrq])
1038 /* don't run CPU */ ;
1039 else if (cpu_is_in_disassemble)
1040 usleep(20000);
1041 else
1042 {
1043 for (a=0;a<8;a++)
1044 if ((breakpt[a]&65535) == PC)
1045 if (breakpt[a]>>16)
1046 { breakpt[a] -= 65536;
1047 print_breaks();
1048 break;
1049 }
1050 if (a == 8 || breakpt[a]>>16)
1051 { if (stream)protocol();
1052 decode(0,1); /* here we decode and execute the current opcode */
1053 if (cpu_is_in_disassemble || speed <= 1) print_panel();
1054 else if (speed==4)
1055 {print_regs();print_ticks();print_halt();print_flags();}
1056 else
1057 { if (ticks>=last_ticks+speed)
1058 print_sp_and_pc(),print_ticks(),print_halt();
1059 }
1060 }
1061 else
1062 { cpu_is_in_disassemble=1; print_panel();
1063 }
1064 }
1065 if (cpu_pin[busrq])
1066 c=no_key_code; /* no keyboard input possible */
1067 else
1068 {
1069 if (cpu_is_in_disassemble) keyboard_disabled=0;
1070 c = !keyboard_disabled && c_kbhit() ? c_getkey() : no_key_code;
1071 if (cpu_is_in_disassemble && c != no_key_code) set_cpu_pin(halt,0);
1072 }
1073 if (c != no_key_code)
1074 switch(c)
1075 {
1076 case '?':
1077 case 'h':
1078 case 'H':
1079 show_keys();
1080 print_panel();
1081 break;
1082
1083 /* case 'q': too dangerous */
1084 case 'Q': /* quit */
1085 c_shutdown();
1086 return 0;
1087
1088 case 'x':
1089 case 'X':
1090 string[0]=0;
1091 ask_str(string,"Execute instruction: ",40);
1092 cpu_is_in_x_mode= 1;
1093 io_address=tmp_memory;
1094 set_cpu_pin(iorq,1);
1095 old_pc=PC;
1096 set_start_address(0);
1097 disable_pseudo=1;
1098 if (!compile(string-1))
1099 { disable_pseudo=0;
1100 PC=0;
1101 decode(&old_pc,1);
1102 }
1103 else
1104 disable_pseudo=0;
1105 set_cpu_pin(iorq,0);
1106 io_address=NULL;
1107 cpu_is_in_x_mode= 0;
1108 print_panel();
1109 break;
1110
1111 case ' ': /* move to next instruction */
1112 decode(0,2);
1113 print_panel();
1114 break;
1115
1116 case K_BACKSPACE: /* exec one instruction */
1117 if (!cpu_is_in_disassemble) break;
1118 if (stream)protocol();
1119 decode(0,1);
1120 print_panel();
1121 break;
1122
1123 case 'f': /* toggle flag */
1124 case 'F':
1125 ask_flag();
1126 print_panel();
1127 break;
1128
1129 case '=':
1130 ask_register();
1131 break;
1132
1133 case 's': /* change SP */
1134 x=ask_x("SP=",SP);
1135 if (x>65535){c_bell();print_status();break;}
1136 cpu_is_in_disassemble=1;
1137 SP=x;
1138 print_panel();
1139 break;
1140
1141 case '+': /* speed */
1142 if (!speed) speed = 1;
1143 else if (speed < 15000) speed <<=2;
1144 print_speed();
1145 break;
1146
1147 case '-': /* speed */
1148 if (speed > 1) speed >>= 2;
1149 else if (cpu_is_in_disassemble) speed =0;
1150 print_speed();
1151 break;
1152
1153 case 'r': /* toggle cpu_wait/run */
1154 case 'R':
1155 if (!cpu_pin[halt] || c=='R') cpu_is_in_disassemble= !cpu_is_in_disassemble;
1156 if (!cpu_is_in_disassemble && !speed) speed=1;
1157 print_panel();
1158 break;
1159
1160 case 'i': /* change IM */
1161 case 'I':
1162 IM++;
1163 IM%=3;
1164 print_panel();
1165 break;
1166
1167 case 't': /* toggle disassembling numbers */
1168 /* 0: default, 1: decimal, 2: hexadecimal, 3: hexadecimal with prefix */
1169 MODE= (MODE&~3) | ((MODE&3)+1 &3);
1170 print_panel();
1171 break;
1172
1173 case 'j': /* toggle disassembling of address displacements (jr/djnz) */
1174 /* 0: relative, 4: absolute 4 digit hexadecimal, 8,12: K-labels,V-labels */
1175 MODE= (MODE&~12) | ((MODE&12)+4 &12);
1176 print_panel();
1177 break;
1178
1179 case '.': /* enter instruction */
1180 set_start_address(MEMP);
1181 do {
1182 sprintf(string,"0x%04x: ",MEMP);
1183 if (ask_str(string,"Put instruction into memory: ",40))break;
1184 compile(string+7);
1185 MEMP=get_current_address();
1186 print_panel();
1187 } while (string[0]);
1188 break;
1189
1190 case K_ENTER: /* enter instruction */
1191 string[0]=0;
1192 ask_str(string,"Put instruction at PC: ",40);
1193 set_start_address(PC);
1194 compile(string-1);
1195 print_panel();
1196 break;
1197
1198 case '^': /* toggle EI/DI */
1199 IFF2=IFF1;
1200 IFF1^=1;
1201 print_panel();
1202 break;
1203
1204 case '*':
1205 clear_user_regs();
1206 reset_banks();
1207
1208 case '@':
1209 #ifdef Z80_CTC
1210 reset_ctc();
1211 #endif
1212 reset_cpu();
1213 last_ticks=0;
1214 print_panel();
1215 break;
1216
1217 case '#':
1218 clear_memory();
1219 print_panel();
1220 break;
1221
1222 case '&': /* init stack_halt */
1223 stack_halt();
1224 print_panel();
1225 break;
1226
1227 case '$':
1228 last_ticks=0;
1229 set_tics(0);
1230 print_ticks();
1231 break;
1232
1233 case 'p': /* ask about address */
1234 case 'P':
1235 x=ask_x("PC=",PC);
1236 if (x>65535){c_bell();print_status();break;}
1237 cpu_is_in_disassemble=1;
1238 PC=x;
1239 print_panel();
1240 break;
1241
1242 case 'u': /* defm */
1243 case 'U':
1244 sprintf(string,"0x%04x: defm \"",MEMP);
1245 if (ask_str(string+13,string,100))break;
1246 string[strlen(string)]='"';
1247 set_start_address(MEMP);
1248 compile(string+7);
1249 print_panel();
1250 break;
1251
1252 case 'w': /* defw */
1253 case 'W':
1254 sprintf(string,"0x%04x: defw ",MEMP);
1255 if (ask_str(string+12,string,64))break;
1256 set_start_address(MEMP);
1257 compile(string+7);
1258 print_panel();
1259 break;
1260
1261 case 'v': /* defb */
1262 case 'V':
1263 sprintf(string,"0x%04x: defb ",MEMP);
1264 if (ask_str(string+12,string,64))break;
1265 set_start_address(MEMP);
1266 compile(string+7);
1267 print_panel();
1268 break;
1269
1270 case K_TAB:
1271 follow^=1;
1272 print_panel();
1273 break;
1274
1275 case 'm': /* ask about start of memory dump */
1276 case 'M':
1277 follow=0;
1278 x=ask_x("Enter memory address: ",MEMP);
1279 if (x>65535){c_bell();break;}
1280 MEMP=x;
1281 print_panel();
1282 break;
1283
1284 case 'L': /* load */
1285 if (ask_str(load_name,"Load file: ",40)){c_bell();print_status();break;}
1286 stream=fopen(load_name,"rb");
1287 if (!stream){stream=0;error_msg(load_name,"Can't read file");print_status();break;}
1288 if (read_header(stream,&start,&x))
1289 {warning("Not a Z80 ASM file"); start=ask("Load to address: ",PC);}
1290 else
1291 { sprintf(string,"starting at 0x%x %u bytes put",a,x); warning(string); }
1292 dma_write(start,x,stream);
1293 fclose(stream);
1294 stream=0;
1295 print_panel();
1296 break;
1297
1298 case 'S': /* save */
1299 if (ask_str(save_name,"Save as: ",40)){c_bell();break;}
1300 x=ask("Length: ",0);
1301 if (PC+x>65536)break;
1302 stream=fopen(save_name,"wb");
1303 if (!stream){stream=0;error_msg(save_name,"Can't write to file ");print_status();break;}
1304 write_header(stream,PC);
1305 dma_read(PC,x,stream);
1306 fclose(stream);
1307 stream=0;
1308 print_panel();
1309 break;
1310
1311 case 'D': /* dump/disassemble */
1312 if (ask_str(save_name,"Disassemble to: ",40)){c_bell();break;}
1313 sprintf(string,"0x%04x - ",PC);
1314
1315 x=ask_x(string,0);
1316 if (x>65536 || x < PC)
1317 {error_msg("","memory wrap_around");print_status();break;}
1318 stream=fopen(save_name,"a");
1319 if (!stream)
1320 {stream=0;error_msg(save_name,"Can't append to file");print_status();break;}
1321 row = -2;
1322 if (MODE&8)
1323 { hash_table_init();
1324 MODE |= 16;
1325 }
1326 old_pc=PC;
1327 while (PC <= x)
1328 {
1329 current_pc=PC;
1330 decode(0,0);
1331 if (!(MODE&16))
1332 fprintf(stream,"\n");
1333 if (PC < current_pc) break;
1334 }
1335 PC=old_pc;
1336 if (MODE&16)
1337 { char blanks[32];
1338 for (a=0;a<31;a++)
1339 blanks[a]=' ';
1340 blanks[a]=0;
1341 MODE &= ~16;
1342 if (labels=table_entries())
1343 { ele= malloc(labels*sizeof(struct info));
1344 for(a=0;next_table_entry(&ele[a].label,&ele[a].value,&ele[a].lineno);a++);
1345 qsort(ele,labels,sizeof(struct info),compare_addr);
1346 }
1347 next_label_index=0;
1348 old_pc=PC;
1349 fprintf(stream,"%sORG 0x%04x\n",blanks,old_pc);
1350 while (PC <= x)
1351 {
1352 current_pc=PC;
1353 decode(0,0);
1354 fprintf(stream,"\n");
1355 if (PC < current_pc) break;
1356 }
1357 PC=old_pc;
1358 }
1359 if (MODE&8)
1360 {
1361 char blanks[23];
1362 b=0;
1363 for (a=0;(unsigned)a<labels;a++)
1364 if (ele[a].label[0]) b++;
1365 if (labels)
1366 fprintf(stream,";\n; %u Used Labels %u Undefined Labels:\n",labels-b,b);
1367 if ((unsigned)b<labels)
1368 { for (a=0;a<23;a++)
1369 blanks[a]=' ';
1370 blanks[a]=0;
1371 }
1372 for (a=0;(unsigned)a<labels;a++)
1373 if (ele[a].label[0])
1374 fprintf(stream,"%s%5s EQU 0x%04hx\n",blanks,ele[a].label,ele[a].value);
1375 free(ele);
1376 free_hash_table();
1377 }
1378 fclose(stream);
1379 stream=0;
1380 print_panel();
1381 break;
1382
1383 case '\"': /* protocol execution */
1384 if (ask_str(proto_name,"Protocol into: ",40)){c_bell();break;}
1385 stream=fopen(proto_name,"a");
1386 if (!stream){stream=0;error_msg(proto_name,"Can't append to file");print_status();break;}
1387 fprintf(stream," PC mnemonic flags A B C D E H L "
1388 " A' B' C' D' E' H' L' IX IY SP\n");
1389 print_status();
1390 break;
1391
1392 case '!': /* toggle keyboard interrupt */
1393 keyboard_disabled^=1;
1394 print_status();
1395 break;
1396
1397 case K_ESCAPE: /* NMI */
1398 nmi_handler();
1399 print_panel();
1400 break;
1401
1402 case '%': /* ask about break point */
1403 for (a=0;a<8;a++)
1404 if ((breakpt[a] & 0xffff) == MEMP)
1405 break;
1406 if (a==8)
1407 for (a=0;a<8;a++)
1408 if ((breakpt[a]>>16 & 0xffff) == 0)
1409 break;
1410 if (a==8) {c_bell();break;}
1411 x=ask_x("Enter breakpoint count: ",breakpt[a]>>16);
1412 if (x>65535){c_bell();break;}
1413 breakpt[a] = MEMP | x<<16;
1414 print_breaks();
1415 break;
1416
1417 MEMP=x;
1418 print_panel();
1419 break;
1420
1421 default:
1422 c_bell();
1423 break;
1424 }
1425 if (cpu_is_in_disassemble) emu=0; /* really finish emulation mode ?? */
1426 if (IFF0)
1427 IFF2=IFF1=1;
1428 else if (cpu_pin[reset])
1429 reset_cpu();
1430 else if (cpu_pin[busrq])
1431 /* don't serve interrupts */ ;
1432 else if (IFF3)
1433 nmi_handler();
1434 else
1435 check_pending_interrupts();
1436 }
1437 c_shutdown();
1438 return 0;
1439 }
1440